int tab[100]; // tableau de 100 entiers int *p1 = &(tab[0]); // p1 pointe vers le premier element de tab int *p2 = tab; // p2 pointe "au debut" de tab -- donc pareil
#include <iostream>
using namespace std;
int main() {
int tab[10];
const int nElem(10);
for(int k(0); k<nElem; k++) {
cin >> tab[k];
}
int somme(0);
for(int k(0); k<nElem; k++) {
somme += tab[k];
}
cout << somme << "\n";
return 0;
}
void * malloc (size_t taille); void free (void * pointeur);Le type de pointeur void * sert de "type générique". De plus, il permet de "cacher" temporairement une structure plus riche. Utilisant le typecast, on peut ensuite retrouver la structure (à condition de "cast"er vers le type correct).
pStr -> NomDuMembreTravail à faire
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int a,b;
} Toto;
void *fCreation(int x, int y) {
Toto *pToto = (Toto *)malloc(sizeof(Toto));
pToto -> a = x;
pToto -> b = y;
return (void*)pToto; // typecast vers void*
}
void fAffichage(void *ptr) {
Toto *pToto = (Toto *)ptr; // typecast vers Toto *
printf("Toto: %d %d\n",pToto->a,pToto->b);
}
int main() {
void *p = fCreation(1,2);
/*printf("TotoMain: %d %d\n",p->a,p->b);*/
fAffichage(p);
free(p);
return(0);
}
int main() {
void *p = fCreation(1,2);
printf("TotoMain: %d %d\n",p->a,p->b);
fAffichage(p);
free(p);
return(0);
}
int main() {
void *p = fCreation(1,2);
fAffichage(p);
free(p);
return(0);
}
donc qui ne parle plus de Toto.
Que faudrait-il quand même donner d'autre pour qu'on
puisse compiler et linker un tel main() avec cette
bibliothèque ? (Indication : c'est ce qu'on fait tout le temps
avec stdio.h etc). Attention -- on n'a pas besoin de la
définition de Toto.
typedef TYPEDERETOUR (*NOM)(TYPEPARAM1 PARAM1, TYPEPARAM2 PARAM2, ...)
#include <stdio.h>
typedef void (*PAppFunc)(void *dest, void **ppElem);
void accumulerInt(void *acc, void **ppElem) {
int *pAcc = (int *)acc;
int **pElem = (int **)ppElem;
*pAcc += **pElem;
(*pElem)++;
}
void balayerAppliquer(void *tableau, const int nElem, PAppFunc pAppFunc, void *base) {
int k;
for(k = 0; k<nElem; k++) {
pAppFunc(base,&tableau);
}
}
int main() {
int tab[10];
const int nElem = 10;
int k;
int somme = 0;
for(k = 0; k<nElem; k++) {
scanf("%d",tab+k);
}
balayerAppliquer(tab,10,accumulerInt,&somme);
printf("%d\n",somme);
return 0;
}
0 0000 0 0 1 0001 1 1 2 0010 2 2 3 0011 3 3 4 0100 4 4 5 0101 5 5 6 0110 6 6 7 0111 7 7 8 1000 10 8 9 1001 11 9 10 1010 12 A 11 1011 13 B 12 1100 14 C 13 1101 15 D 14 1110 16 E 15 1111 17 F 16 10000 20 10algèbre booléenne de base
OU BINAIRE | 0 1
------------+----------- Operateur | en C/C++
0 | 0 1
|
1 | 1 1
|
ET BINAIRE | 0 1
------------+----------- Operateur & en C/C++
0 | 0 0
|
1 | 0 1
|
OU exclusif | 0 1
------------+----------- Operateur ^ en C/C++
0 | 0 1
|
1 | 1 0
|
Parmi les opérations de base dans cette catégorie on a la mise
à un ou respéctivement à zéro d'un bit
de rang donné, ainsi que le test d'un bit de rang donné, et
également le fait d'inverser un bit (donc s'il vallait un on le met
à zéro, et s'il vallait zéro, on le met à un).
La manière générique de procéder est l'utilisation de
masques, puisque le OU binaire d'une valeur quelconque avec 0 la laisse
inchangée, ainsi que le ET binaire avec 1. Autrement dit
qqchose OU 0 == laMemeChose qqchose ET 1 == laMemeChoseet sym\'etriquement, le OU binaire d'une valeur quelconque avec la valeur 1 la transforme en 1, etc.
qqchose OU 1 == 1 qqchose ET 0 == 0Enfin, on dispose d'un opérateur dit de "shift gauche", le <<, qui "déplace" les bits vers la gauche
0001 << 2 donnera 0100et aussi de l'opérateur de négation de bit, le ~. Avec tout ceci, on peut écrire une fonction qui prend deux arguments : un rang et une valeur, dont elle mettra le bit de rang donné à zéro (quelle que soit sa valeur initiale, et sans toucher aux autres bits):
int mettreBitAZero(int valeur, int rang) {
int masque = 1 << rang; /* masque sera 00..010...0 */
return valeur & ~masque; /* ET binaire avec 11..101...1 */
}
int mettreBitAUn (int valeur, int rang); int inverserBit (int valeur, int rang); int testerBitAUn (int valeur, int rang); int testerBitAZero(int valeur, int rang);
r XOR 0 donne toujours r
r XOR 1 donne toujours l'inverse de r
r XOR r donne toujours 0
alors si on considère deux bits arbitraires r et s,
(r XOR s) XOR r donne toujours s
car si r et s sont identiques, on a
(r XOR r) XOR r == 0 XOR r == r (donc == s par hypothese)et s'ils sont diff\'erents,
(r XOR s) XOR r == 1 XOR r == l'inverse de r (donc == s par hypothese)Soit la fonction
void rebelotte(int *pA, int *pB) {
int c = *pA;
*pA = *pB;
*pB = c;
}
qui permute les deux valeurs. Écrivez une fonction similaire qui
n'utilise pas une troisième variable, et qui se sert de XOR, en
utilisant la relation prouvée ci-avant
(r XOR s) XOR r donne toujours s
(a XOR b) XOR b
class MaPetiteChaine {
public:
MaPetiteChaine(const char* data = "");
virtual ~MaPetiteChaine();
virtual const char* to_cstr() const;
private:
char* m_dataP;
};
MaPetiteChaine::MaPetiteChaine(const char* dataP) :
m_dataP(new char[strlen(dataP)+1]) {
strcpy(m_dataP,dataP);
}
MaPetiteChaine::~MaPetiteChaine() {
delete [] m_dataP;
}
const char* MaPetiteChaine::to_cstr() const {
return m_dataP;
}
int main() {
MaPetiteChaine salut("Bonjour tout le monde");
cout << salut.to_cstr() << endl;
// on en fait une copie dynamiquement
MaPetiteChaine* reSalutP = new MaPetiteChaine(salut);
// on utilise la copie et l'original, tout baigne
cout << reSalutP->to_cstr() << endl;
cout << salut.to_cstr() << endl;
delete reSalutP; // on nettoie la copie
reSalutP = 0; // pour etre bien clean
// et on devrait pouvoir encore utiliser l'original....
cout << salut.to_cstr() << endl; // a l'air ok, mais BOUM !
} // et encore BADABOUM ! mais qu'est-ce qu'on a fait ?..
cout << "Effacement de m_dataP " << reinterpret_cast<long int>(m_dataP) << "\n";au début du destructeur, et recompilez et ressayez. Vous devrez constanter que les deux valeurs affichées sont bien les mêmes.
new char[strlen(dataP)+1000]donc 999 de caractès de plus. Aucune autre modification. Recompilez, relancez, et admirez le badaboum, assez explicite
*** glibc detected *** ./a.out: double free or corruption (!prev) ======= Backtrace: ========= ...
#include <stdio.h>
#include <stdlib.h>
int main() {
int numberOfIter = 5;
int numberOfTabs = 4;
int eachTabLength = 4;
int kIter;
for(kIter = 0; kIter < numberOfIter; kIter++) {
// alloc 'em
char **tab = (char**)malloc(numberOfTabs * sizeof(char*));
int kTab;
for(kTab = 0; kTab < numberOfTabs; kTab++) {
tab[kTab] = (char *)malloc(eachTabLength * sizeof(char));
int kElem;
for(kElem = 0; kElem < eachTabLength-1; kElem++) {
tab[kTab][kElem] = 'A' + kTab + kElem;
}
tab[kTab][eachTabLength-1] = '\0';
}
// use 'em
for(kTab = 0; kTab < numberOfTabs; kTab++) {
printf("%s ",tab[kTab]);
}
// free 'em all
free(tab); // or at least u think so
printf("Free to go\n");
}
printf("Good bye.\n");
return(0);
}
valgrind fuiteMemoire.runet admirez le bilan détaillé. Que nous dit-il?