View Full Version : [C++] int, array byte
INT32 a = 0x00401600;
char c[] = { 0x00, 0x40, 0x16, 0x00 };
perchè sprintf c dà 0x0028fec4 :confused:
lorenzo001
04-07-2014, 18:22
Quale sprintf ?
INT32 a = 0x00401600;
INT32 b = 0x004016B0;
char c[] = { 0x00, 0x40, 0x16, 0x00 };
char d[] = { 0x00, 0x40, 0x16, 0xB0 };
printf("0x%08x\n0x%08x\n\n", a, b);
printf("0x%08x\n0x%08x\n\n", c, d);
M'è scappata una s di troppo :fagiano:
printf("%s\n", c == &c[0] ? "y" : "n" );
lorenzo001
04-07-2014, 19:00
c e d sono array e quindi visualizzi l'indirizzo dell'array, ovvero del suo primo elemento (che è quello che ti ha spiegato van9)
Per quello che vuoi fare tu, devi indicare che l'indirizzo in questione punta ad un intero e quindi visualizzare il valore puntato, ovvero
printf("0x%08x\n0x%08x\n\n", *((int *)c), *((int *)d));
Tieni presente però che in memoria i valori sono in ordine inverso e quindi devi scrivere
char c[] = { 0x00, 0x16, 0x40, 0x00 };
char d[] = { 0xB0, 0x16, 0x40, 0x00 };
c e d sono array e quindi visualizzi l'indirizzo dell'array, ovvero del suo primo elemento (che è quello che ti ha spiegato van9)
Per quello che vuoi fare tu, devi indicare che l'indirizzo in questione punta ad un intero e quindi visualizzare il valore puntato, ovvero
printf("0x%08x\n0x%08x\n\n", *((int *)c), *((int *)d));
d'oh :doh: mi confondo sempre con i puntatori
Tieni presente però che in memoria i valori sono in ordine inverso e quindi devi scrivere
char c[] = { 0x00, 0x16, 0x40, 0x00 };
char d[] = { 0xB0, 0x16, 0x40, 0x00 };
Quindi i byte di a e c in memoria sono invertiti ?
lorenzo001
04-07-2014, 19:29
I byte che compongono l'intero a sono nell'ordine che ti ho indicato, dal meno significativo al più significativo ( per i processori Intel, ordine little-endian, vedi http://it.wikipedia.org/wiki/Ordine_dei_byte )
in realtà tutti gli esempi riportati sino ad ora sono più "scorciatoie" che altro.
è possibile trattare array con l'aritmetica dei puntatori ma un array non è un puntatore e soprattutto ci sono modi migliori di informare il tuo compilatore che stai trattando un array.
Inoltre questo codice è puro C, non esiste nulla che sia C++, non confondete i due linguaggi.
Se dato un array sei interessato ad estrarre o visualizzare gli indirizzi dei suoi elementi ( mi sembra di capire che il problema sia questo ) questo piccolo programma in C ( C99 ) con relativa funzione dovrebbe fare al caso tuo
#include <stdlib.h>
#include <stdio.h>
void printAddr(int (*arr)[], size_t s)
{
for (size_t i = 0; i < s; i++)
{
printf("%p %d\n", &(*arr)[i], *(&(*arr)[i]));
}
}
int main()
{
int c[] = {1, 54, 42, 44, 33};
// esempio su singola riga senza uso
// di alcuna funzione
// printf("%p %d\n", &c[2], *(&c[2]));
printAddr(&c, 5);
return EXIT_SUCCESS;
}
il punto chiave è che se hai un array arr e vuoi l'indirizzo dell'elemento che trovi con un indice di valore 3, per avere l'indirizzo di quell'elemento usi la sintassi &arr[3] .
è possibile trattare array con l'aritmetica dei puntatori ma un array non è un puntatore
non è un puntatore costante che punta al primo elemento :confused:
non è un puntatore costante che punta al primo elemento :confused:
dipende a cosa ti riferisci e in quale contesto.
in breve non è possibile dare una risposta in un post, bisogna conoscere il linguaggio e come la macchina e il compilatore opera, comunque sia ritorno a specificare che
puntatore != array
nel mondo della programmazione, specialmente in C e C++, esiste il fenomeno dell'aliasing, e specialmente in C++ l'aliasing è una brutta bestia che può nascondere perdite di performance, https://it.wikipedia.org/wiki/Aliasing_%28programmazione%29
quando tratti un array come puntatore introduci dell'aliasing, e questo è il motivo per cui all'atto pratico non vedi differenze, ma concettualmente usare un array come o attraverso un puntatore è una cattiva soluzione per diversi motivi.
il problema è anche teorico perché a tutti i "prof" che ho conosciuto piace semplificare e pure troppo; il concetto di puntatore è molto più facile da spiegare e assimilare di tutto il resto, e quindi ogni buon prof di informatica ti ripete che tutto può essere un puntatore e tutti son felici e contenti, stessa cosa dicasi per alcuni libri. Inutile dire che non è così.
se sei interessato a studiare il linguaggio ci sono gli standard ISO ( ISO/IEC 9899:1999 per il C99 ) se sei un programmatore occasionale il tuo codice sarà orribile ma all'atto pratico non vedrai molte differenze ( "il programma funziona!" cit. ) e vivrai contento .
Tralasciando le questioni di performance (premature optimization is the root of all evil), la cosa è un pelo delicata.
Un esempio semplice per capire come il compilatore tratta differentemente le cose:
char mio_array[20];
printf("SizeOf: %lu\n", sizeof(mio_array)); // stampa 20
char* mio_array = alloca(20); // alloca 20 bytes sullo stack
printf("SizeOf: %lu\n", sizeof(mio_array)); // stampa 4 o 8 (a seconda dei casi)
vbextreme
06-07-2014, 08:24
@freaxx io avrei preferito altre alternative al tuo codice, quali:
void old_printAddr(int (*arr)[], size_t s)
{
for (size_t i = 0; i < s; i++)
{
printf("%p %d\n", &(*arr)[i], *(&(*arr)[i]));
}
}
void simple_printAddr(void *arr, size_t s)
{
int* a = (int*) arr;
while(s--)
{
printf("%p %d\n", a, *a);
a++;
}
}
void versatile_printAddr(void *arr, size_t s, size_t n, const char* vw)
{
char* a = (char*) arr;
char v1[80];
char v2[80];
while (n--)
{
sprintf(v1,"%p ",a);
sprintf(v2,vw,*a);
strcat(v1,v2);
puts(v1);
a += s;
}
}
int main()
{
int c[] = {1, 54, 42, 44, 33};
char x[] = {'a','b','c'};
// esempio su singola riga senza uso
// di alcuna funzione
// printf("%p %d\n", &c[2], *(&c[2]));
puts("Simple Vector int");
simple_printAddr(&c, 5);
puts("Versatile Vector int");
versatile_printAddr(&c, sizeof(int), 5,"%d");
puts("Versatile Vector char");
versatile_printAddr(&x, sizeof(char), 3,"%c");
return 0;
}
Ho poi bloccato lo standard c99 quindi non l'ho nemmeno compilato il tuo codice.
||=== Build: Debug in iop (compiler: GNU GCC Compiler) ===|
main.c||In function ‘old_printAddr’:|
main.c|71|error: ‘for’ loop initial declarations are only allowed in C99 mode|
main.c|71|note: use option -std=c99 or -std=gnu99 to compile your code|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
Niente flame però! solo questione di gusti personali.
in soldoni, si. la principale differenza è che è un puntatore costante e la memoria è sempre allocata al momento della definizione dell'arra stesso.
No, e basta passare il nome di un array come parametro ad una function per dimostrarlo: il nome dell'array decade immediatamente a puntatore ed è possibile assegnare al nome stesso un nuovo valore (ovvero niente comportamento da "puntatore costante"). Per un esempio di array la cui memoria non è allocata a tempo di definizione vedi i flexible members in C99.
non è un puntatore costante che punta al primo elemento :confused:
No. Un array, un puntatore e un puntatore costante sono tre cose differenti.
Il nome di un array viene convertito ("decade") a puntatore quando serve, ma questo non lo rende o trasforma in un puntatore.
Due sono le cose: o ha ragione Dennis Ritchie (autore del C) quando dice che, date le evidenti difficoltà dei più a capire la natura di arrays e puntatori in C, stiamo parlando di un errore di design e quindi è facile che i più trovino difficoltà.
Oppure i programmatori non si applicano davvero/non vanno in fondo alle questioni.
Se vuoi imparare una volta e per tutte come stanno (semplicemente) le cose, studiati attentamente http://cm.bell-labs.com/who/dmr/chist.html e dopo vedrai non ci sarà più alcuna confusione.
Mi hanno passato questo:
Deitel & Deitel - C, Corso completo di programmazione
va bene se (re)inizio con quello :confused:
in realtà tutti gli esempi riportati sino ad ora sono più "scorciatoie" che altro.
Ma se non hai nemmeno centrato la richiesta dell'OP! (vedi sotto)
è possibile trattare array con l'aritmetica dei puntatori ma un array non è un puntatore e soprattutto ci sono modi migliori di informare il tuo compilatore che stai trattando un array.
A vole essere precisi semmai dovevamo informare noi l'OP che aveva un overflow in atto. Noia e pigrizia da parte mia l'altro giorno.
Inoltre questo codice è puro C, non esiste nulla che sia C++, non confondete i due linguaggi.
Io non confondo proprio nulla e nemmeno Lorenzo mi pare - quanto scritto è per definizione codice C++ e quindi non si capisce di che ti lamenti. Tra l'altro come qualunque esperto di C++ dotato di senso pratico e gusto, uso sempre stdio al posto di quella schifezza stateful di iostream e proprio in questo esempio non c'è discussione al riguardo.
Se dato un array sei interessato ad estrarre o visualizzare gli indirizzi dei suoi elementi ( mi sembra di capire che il problema sia questo )
No, l'OP si chiedeva perché due chiamate a printf non producessero lo stesso risultato - il problema è il classico di chi pensa che attraverso il solo nome di una struttura dati possa avere accesso unitario/completo ad essa.
questo piccolo programma in C ( C99 ) con relativa funzione dovrebbe fare al caso tuo
Ma non era taggato "C++" il thread? In C++ valido, e molto più chiaramente:
void _printAddr(int arr[], size_t s)
{
for (size_t i = 0; i < s; i++)
{
printf("%p %d\n", (void *) &arr[i], arr[i]);
}
}
il punto chiave è che se hai un array arr e vuoi l'indirizzo dell'elemento che trovi con un indice di valore 3, per avere l'indirizzo di quell'elemento usi la sintassi &arr[3] .
Più che altro restava da chiarirgli la questione dello storage, con cui può divertirsi tramite qualcosa tipo
size_t n = sizeof(c)/sizeof(c[0]);
for (size_t i = 0; i < n; i++)
printf("%s%02x%s", !i ? "0x" : "", c[i], i == n-1 ? "\n" : "");
e/o
printf("0x%02x%02x%02x%02x\n",
*((int *)c) & 0xff,
(*((int *)c) >> 8) & 0xff,
(*((int *)c) >> 16) & 0xff,
(*((int *)c) >> 24) & 0xff);
Tutto rigorosamente scritto al volo e non testato. Il problema dell'overflow è lasciato come esercizio per l'OP.
Tralasciando le questioni di performance (premature optimization is the root of all evil), la cosa è un pelo delicata.
E' più una questione strutturale e di linguaggio che altro - chi conosce anche Fortran (arrays "veri", restricted pointers, etc.) lo sa bene. E no, ovviamente non si risolve nulla utilizzando solo ed esclusivamente gli arrays piuttosto che i puntatori (perché questo non garantisce all'optimizer l'assenza di aliasing - vedi anche la keyword restrict in C99 per una direzione standardizzata sulla faccenda).
@var9 di precisazioni se ne possono fare sempre tante, il codice era chiaramente un esercizio in C a differenza di quanto scritto nel titolo ( C++ ).
Considero comunque quanto postato un passo in avanti nella giusta direzione per l'OP, è inoltre una soluzione molto più asciutta e compatta, con 1-2 novità che OP può studiare per comprendere meglio come si possa implementare quanto chiesto.
Onestamente in questi frangenti gradisco più usare C++ che C, il motivo per il quale non ho offerto un esempio l'ho già menzionato, peraltro OP ha appena citato un libro sul C .
La gestione della memoria in C e/o C++ è sempre un punto critico, è talmente importante che molto spesso la fonte dei problemi in termini di affidabilità e performance in software scritto usando questi due linguaggi è quasi sempre da ricercare li e raramente altrove ( considerando un codice grammaticalmente e logicamente corretto ) .
Ma non mi metto certo a discutere di gestione della memoria in un post su un forum, solo per trattare gli allocatori in C++ servirebbe un libro, se ci mettiamo pure le varie differenze specifiche alle varie piattaforme, come il comportamento delle funzioni della famiglia *alloc* ci servono mesi di trattazione in C e C++ .
Tutto ciò è sicuramente interessante ma inopportuno per un post di risposta ad una domanda semplice come questa che è in realtà un piccolo esercizio per inziare. Se OP vorrà si prenderà un bel compilatore, debugger e profiler, un bel manuale o libro sul C, e approfondirà da solo.
Non intendo entrare in polemica con nessuno ma è la mia personale visione su come si dovrebbe insegnare un linguaggio come il C o il C++ ad un novizio; un esempio che può apparire stupido ma stupido non è
listato 1
int main()
{
...
return 0;
}
listato 2
#include <stdlib.h>
int main()
{
...
return EXIT_SUCCESS;
}
e la domanda in questo caso è: quale dei due prototipi scegliereste come modello per creare esempi in codice C per un novizio ?
Adesso fate mente locale a quante volte avete visto persone scrivere return 0; anziché return EXIT_SUCCESS;, oppure quante volte persone che fanno questo lavoro hanno usato return EXIT_SUCCESS; senza usare la giusta inclusione, il giusto header. Questo genere di cose viene prima della teoria sulla memoria e le allocazioni e deallocazioni, se non conosci la sintassi da usare per dichiarare un puntatore ad un array o come si può dedurre l'indirizzo di un elemento di un array dato il suo indice, della teoria sulla memoria non te ne fai nulla; anche perché poi inizi a prendere questa sintassi come abitudine e finirai per scrivere sempre return 0; anche sapendo che è un approccio non standard e meno portabile.
Mi hanno passato questo:
Deitel & Deitel - C, Corso completo di programmazione
va bene se (re)inizio con quello :confused:
si, i Deitel credo che vadano bene per un novizio.
da notare anche che il libro di riferimento per il C ( http://www.amazon.com/The-Programming-Language-2nd-Edition/dp/0131103628/ , esiste anche l'edizione tradotta in italiano ) è più strutturato come un manuale che come un libro per i novizi che vogliono partire con il C, è un po' più formale e meno incentrato su questioni di programmazione generale, rimane tuttavia una ottima alternativa.
@var9 di precisazioni se ne possono fare sempre tante, il codice era chiaramente un esercizio in C a differenza di quanto scritto nel titolo ( C++ ).
Considero comunque quanto postato un passo in avanti nella giusta direzione per l'OP, è inoltre una soluzione molto più asciutta e compatta, con 1-2 novità che OP può studiare per comprendere meglio come si possa implementare quanto chiesto.
Onestamente in questi frangenti gradisco più usare C++ che C, il motivo per il quale non ho offerto un esempio l'ho già menzionato, peraltro OP ha appena citato un libro sul C .
In verità non si è mica capito perché ci hai (erroneamente) accusati di confondere i linguaggi per poi non usare il C++ "puro" che tanto gradisci in questi frangenti - la richiesta sul libro C non centra visto che è decisamente posteriore. Sei sempre in tempo per spiegare all'OP come funzionano la statefulness nell'iostream, hex, setw, setfill e tutto il cucuzzaro dei manipulators, i namespaces e std per avere anche solo il semplice output formattato equivalente ad una printf("0x%08x\n", 0x004016B0).
La gestione della memoria in C e/o C++ è sempre un punto critico, è talmente importante che molto spesso la fonte dei problemi in termini di affidabilità e performance in software scritto usando questi due linguaggi è quasi sempre da ricercare li e raramente altrove ( considerando un codice grammaticalmente e logicamente corretto ) .
Ma non mi metto certo a discutere di gestione della memoria in un post su un forum, solo per trattare gli allocatori in C++ servirebbe un libro, se ci mettiamo pure le varie differenze specifiche alle varie piattaforme, come il comportamento delle funzioni della famiglia *alloc* ci servono mesi di trattazione in C e C++ .
Tutto ciò è sicuramente interessante ma inopportuno per un post di risposta ad una domanda semplice come questa che è in realtà un piccolo esercizio per inziare. Se OP vorrà si prenderà un bel compilatore, debugger e profiler, un bel manuale o libro sul C, e approfondirà da solo.
Boh, nonsense a manetta qui.
Non intendo entrare in polemica con nessuno ma è la mia personale visione su come si dovrebbe insegnare un linguaggio come il C o il C++ ad un novizio; un esempio che può apparire stupido ma stupido non è
listato 1
int main()
{
...
return 0;
}
listato 2
#include <stdlib.h>
int main()
{
...
return EXIT_SUCCESS;
}
e la domanda in questo caso è: quale dei due prototipi scegliereste come modello per creare esempi in codice C per un novizio ?
Adesso fate mente locale a quante volte avete visto persone scrivere return 0; anziché return EXIT_SUCCESS;, oppure quante volte persone che fanno questo lavoro hanno usato return EXIT_SUCCESS; senza usare la giusta inclusione, il giusto header. Questo genere di cose viene prima della teoria sulla memoria e le allocazioni e deallocazioni, se non conosci la sintassi da usare per dichiarare un puntatore ad un array o come si può dedurre l'indirizzo di un elemento di un array dato il suo indice, della teoria sulla memoria non te ne fai nulla; anche perché poi inizi a prendere questa sintassi come abitudine e finirai per scrivere sempre return 0; anche sapendo che è un approccio non standard e meno portabile.
Eh?? Ma quando mai. Le stai inventando sul momento?
Quando viene raggiunta la } che termina il main lo Standard corrente *garantisce* che il valore ritornato sia 0. Altro che meno portabile, 0 è il valore di ritorno portabile per eccellenza. Sempre per lo Standard, 0 e EXIT_SUCCESS sono inoltre del tutto equivalenti nel segnalare "successful completion". Da notare che il valore di EXIT_SUCCESS è implementation defined, e quindi potrebbe essere diverso dal convenzionale 0 (anche se non ho mai incontrato un'implementazione così). Se così fosse, lo 0 ritornato automaticamente o equivalentemente tramite "return 0;" o "exit(0)" resterebbe tra i due il valore *noto* e garantito per tutti a prescindere. E' anche per questo motivo che tutti lo usano, che vari lint lo hanno sempre riconosciuto e si aspettano di vederlo pena sollevare warnings, etc. "return 0;" è tanto nello Standard quanto ovunque, dallo stesso K&R seconda edizione al King al Van Der Linden a tutti gli altri buoni autori. Le uniche discussioni degna di nota che riguardano ugualmente 0 e EXIT_SUCCESS sono quelle sui freestanding environment, dove quello che accade al termine dei programmi non è standardizzato: il (mancato) senso nel ritornare in automatico un valore in un ambiente dove main non è magari supposto ritorni alcunchè oppure dove non è previsto ritorni del tutto, le questioni di unreachable code e via dicendo. Ma questo è un problema delle specifiche ANSI che sono da sempre incomplete quando non decisamente fatte male, spesso più d'intralcio che chiarificatrici.
In C89 invece la situazione è diversa - main senza un return con un valore (compatibile con il tipo ritornato da main) ritorna uno stato indefinito all'ambiente chiamante. Nel caso di un return e dell'equivalente exit(), 0 e EXIT_SUCCESS sono ancora una volta garantite come assolutamente equivalenti per segnalare successo (e come prima, con zero che è universalmente noto e accettato mentre l'altro resta dipendente dall'implmentazione).
Prima ancora, mi scoccio d'arrivarci che penso basti così.
Non che m'aspettassi qualcosa di diverso da come t'eri presentato. Ma vabbè, almeno le prime pagine dello Standard prima di buttarsi a farsi ganzi in giro, i "mesi di trattazione" e trollate varie sugli altri linguaggi annesse...
è per quello che ho scritto "in soldoni" (a grandi linee). poi potrà fare tutti gli esempi e i controesempi per sapere quando è vero e quando non è, ma dato il contenuto del thread (ovvero molto semplice) la risposta che ho ritenuto più adatta è stata quella più semplice di tutti.
E' tutto lì il problema: non è mai vero. Meglio dare l'unica spiegazione corretta da subito e indirizzare eventualmente alle faqs, non trovi?
@van9 stai sbagliando, sia in relazione al problema sia in relazione allo standard, questo è tutto quello che posso dire .
Mi hanno passato questo:
Deitel & Deitel - C, Corso completo di programmazione
va bene se (re)inizio con quello :confused:
Si. Se poi vuoi spendere qualcosa compra "C Programming: A Modern Approach" di King (2a edizione), è per principianti e così dettagliato che contiene praticamente tutto quello a cui accennavo (per tanti altri libri - Deitel compreso - non è così).
non è mai vero?
quindi questo compila?
int main()
{
int a[10];
int b[20];
a = b;
}
Antonio, è facile. Il nome di un array non è un puntatore costante che punta al primo elemento. Mai. Punto. Sono tipi diversi e distinti per il C, non capire questo significa non capire il type system del C.
a e b sono due array di tipo array-of-T, con T := int.
In "a = b", viene formata una nuova espressione per via del fatto che b decade (salvo eccezioni) a puntatore.
La trasformazione che genera la nuova espressione è una certa t:
t :: array-of-T -> pointer-to-T
prende la b di "int b[20]" e genera un puntatore che sostituiamo idealmente alla b in "a = b".
Un altro esempio di possibile trasformazione è:
t' :: array-of-T -> pointer-to-array-of-T
ovvero quella che verrebbe applicata se nel programma ci fosse "a = &b".
b in tutto questo, è e resta di tipo array-of-T.
Dopo di che, assegnare due array è illegale. Non si può assegnare un tipo pointer-to-T ad un tipo array-of-T. Un lvalue di tipo array-of-T è per definizione non modificabile.
Il tuo programma non compila per via di quanto esposto sopra. I puntatori costanti c'entrano meno di nulla. Se pensi di non poter assegnare ad a perché questo è un "puntatore costante" ti sbagli e non hai capito bene come funziona il C.
'Ste quattro cazzate è quanto genera confusione da decenni. Ogni volta che qualche faina per abbreviare parla di "equivalenza" e robe simili, non aiuta nessuno. Due cose sono equivalenti se e solo se le puoi sempre e comunque sostituire una all'altra. Arrays e pointers sono entità diverse e non equivalenti. Nomi di arrays e constant pointers sono entità diverse e non equivalenti.
I buoni libri tipo il King e le note di Steve Summit (curatore delle faq di comp.lang.c) non entrano così nel dettaglio che manco ce n'è bisogno, ma nemmeno affermano il falso come in "(Il nome di) un array è un puntatore costante al primo elemento". Usano una via di mezzo con anche spiegazioni del tipo """il nome di una variabile array è usata come un "puntatore costante", salvo ad esempio il caso che venga passata come parametro""", con tanto di virgolettato che enfatizza l'analogia. Posto che si è chiarito già che il nome di un array non è un puntatore, che gli array e i puntatori non sono equivalenti/intercambiabili e via dicendo... diviene accettabile. Virgolettati, "quasi", "potrebbe" accompagnati da solide precisazioni sono (in my book) molto diversi dal tuo "in soldoni".
Personalmente sono contrario ad analogie e similitudini se non accompagnate dai sacrosanti "assiomi" del caso ("A non è B; ci sono comunque le circostanze a,b e c in cui B può comparire al posto di A" e via così).
tra l'altro, è opinione ampiamente diffusa e accettata definirlo in quel modo soprattutto agli inizi, e.g.
http://stackoverflow.com/questions/2351544/is-array-name-a-constant-pointer-in-c
An array name is not a constant pointer - however it acts like one in so many contexts (it converts to one on sight pretty much) that for most purposes it is.
From 6.3.2.1/3 "Other operands/Lvalues, arrays,and function designators":
Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type "array of type" is converted to an expression with type "pointer to type" that points to the initial element of the array object and is not an lvalue.
L'essere diffusa non la rende di certo meno sbagliata. Hai preso una citazione a caso in rete, ti rispondo allo stesso modo con una trovata in 2 secs. netti:
Here is how i think you view the matter
You hear someone say that an array name is a constant pointer to its first element
You take the address of that pointer, cast away any const
You happily write some other address into the pointer, and hope that it doesn't crash
You use the array again, expecting it "overlays" now the uninitialized memory region that malloc created.
But that view is flawed. The first point is flawed the most, because an array name is not a constant pointer. If the first point were correct, your snippet would make a lot more sense, actually. But an array name will generate an address value that refers to its first element when you use it in an expression, except in very few cases (sizeof, address-of).
Because that address value is not generated when you use address-of, you will get a pointer to that array instead (which was exactly what you wrote with the address-of operator). Since it makes sense that an array and the first element of it has the same address, the address of an array happens to equal to the address of its first element. So what you actually did was writing into the first element, instead of writing into some pointer (that in reality isn't there).
da http://stackoverflow.com/a/1113990
Efficace esposizione dell'aspetto didattico/sociale della faccenda; unita al lato formale che ho esposto sopra spero non ti lascino più dubbi al riguardo. Nota anche che tra i commenti lo stesso Burr di prima non si lamenta.
Come vedi (e come già con il nostro OP) le spiegazioni alla "for most purposes it is" e "in soldoni" portano solo errori software, di comprensione e quel falso senso di sicurezza ("ho capito", "so come funziona") che poi alla fine genera danni e noie varie nel lungo termine.
@van9 stai sbagliando, sia in relazione al problema sia in relazione allo standard, questo è tutto quello che posso dire .
Hai dimenticato il gnègnègnè.
"""ISO/IEC 9899:201x Committee Draft — April 12, 2011 N1570"""
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
5.1.2.2.3 Program termination
If the return type of the main function is a type compatible with int, a return from the
initial call to the main function is equivalent to calling the exit function with the value
returned by the main function as its argument;11) reaching the } that terminates the
main function returns a value of 0. If the return type is not compatible with int, the
termination status returned to the host environment is unspecified.
...
7.22.4.4 The exit function
Finally, control is returned to the host environment. If the value of status is zero or
EXIT_SUCCESS, an implementation-defined form of the status successful termination is
returned. If the value of status is EXIT_FAILURE, an implementation-defined form
of the status unsuccessful termination is returned. Otherwise the status returned is
implementation-defined
Ovviamente, siccome all'ISO sono scemi e non sanno quello che fanno hanno inserito nello Standard stesso tre (3) esempi completi che chiudono con "return 0;". Perché non provi a segnalarglieli, fessacchiotto.
#include <inttypes.h>
#include <wchar.h>
int main(void)
{
uintmax_t i = UINTMAX_MAX; // this type always exists
wprintf(L"The largest integer value is %020"
PRIxMAX "\n", i);
return 0;
}
pagina 218 in 7.8.2.1
ancora non ho capito se in quelle 4 righe che ho postato a "si comporta come" un puntatore costante a intero oppure no.
poi non mi pare di aver detto che sono la stessa cosa, e questo dal mio primo reply.
Qual'è la definizione di "si comporta come" che applichi al tuo esempio? Il fatto che valga la proprietà di non essere assegnabile?
dimenticavo: se non sono la stessa cosa, e lo stai confermando tu adesso, è ovvio che non sono *mai* la stessa cosa come ho precisato io. Perché mi contesti quest'ultima quindi? Sono o non sono la stessa cosa?
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.