C Бағдарламалау қарапайым көрсеткіштер

Мен оқушыларда жаңадан бастаймын. Міне менің кодексім. (Ескерту: Мен әлі күнге дейін менің коды таза болмайды, сондықтан менің бастамашылар айналасында алуға тырысамын.)

#include 
#include 

int main (int argc, char *argv[]){

int a = 1;
char b = 's';
double c = 3.14;
int *ptra;
int *ptrb;
int *ptrc;

ptra = &a;
ptrb = &b;
ptrc = &c;

printf("I initialised int as %d and char as %c and double as %.2f\n", a, b, c);
printf("The address of A is %p and the contents of A is %d\n", ptra, *ptra);
printf("The address of B is %p and the contents of B is %c\n", ptrb, *ptrb);
printf("The address of C is %p and the contents of C is %.2f\n", ptrc, *ptrc);

Мен келесі нәтижені күткен едім:

I initialised int as 1 and char as s and double as 3.14
The address of A is 0xbf933094 and the contents of A is 1
The address of B is 0xbf933093 and the contents of B is s
The address of C is 0xbf933098 and the contents of C is 3.14

Бірақ орнына мен:

I initialised int as 1 and char as s and double as 3.14
The address of A is 0xbf933094 and the contents of A is 1
The address of B is 0xbf933093 and the contents of B is s
The address of C is 0xbf933098 and the contents of C is 427698.00000

C мазмұнын басып шығарғанда, менде көп адамға көмектесе аламын ба? 3.14 неге алмаймын? (Нөмір шынымен де ұзақ, бірақ бұл мәтіндік жәшікке сәйкес емес :-))

2
Мұнда жауаптардың көпшілігі нүкте жетіспейді. Мәселе туындайды, өйткені өлшемі (қосарланған)> sizeof (int), бұрылыс нүктесінің мәндеріне мантисса қиылысатын биттерді тудырады.
қосылды автор Richard J. Ross III, көзі
Менің ойымша, сіз қос нүкте емес, int.
қосылды автор Hunter McMillen, көзі
Сіз берген кодта көптеген шектеулерді (aka қателерін) қамтиды, олар төмендегі жауаптарда көрсетілген. Педантты C компиляторы оны құрастырудан бас тартады. Сіздің C компиляторыңыз оны қате тексеруге және стандартты емес кеңейтулерге байланысты қабылдауы мүмкін, бірақ кез келген жағдайда диагностикалық хабарлар шығаруы керек. Мұндай қателерді елемеу (тіпті егер код жасалса да) ешқашан жақсы идея емес.
қосылды автор AnT, көзі
@ Ричард Дж. Росс III: Мәселе туындайды, код қате бар. Егер int сияқты бірдей өлшемі бар double дегенді float ауыстырсаңыз, коды әлі де 3.14 код>.
қосылды автор AnT, көзі
Компилятор сізге ескерту және қателер түрінде дұрыс емес әрекеттер туралы ақпарат беру үшін өте күшті әрекет еткен болуы мүмкін. Егер сіз gcc немесе clang пайдалансаңыз, «-Wall-Werror» -ді құрастырған кезде, сіз көп нәрсені тезірек білетіндігіңізді тексеріңіз.
қосылды автор kfsone, көзі
Мен ptrc көрсеткіші int деректер түрін көрсететін етіп орнатылатындығын сезінемін, бірақ іс жүзінде double деректер түрі. int - әдетте 4 байт, double - 8 байт. Көрсеткіш 4 байтты қараңыз, бірақ double мәнінің шын мәнін алу үшін барлық 8-ді оқуы керек. Ақаулықты түзету үшін ptrc сөзін double деп жариялаңыз.
қосылды автор brazilianldsjaguar, көзі

7 жауаптар

ptra , ptrb және ptrc сілтемелері ретінде int . Бірақ көрсеткіштің түрі ол нені білдіретініне негізделеді, сондықтан шын мәнінде:

int    *ptra;
char   *ptrb;
double *ptrc;

specific жағдайда, сіздің бағдарламаңыз double мәнін int көрсеткіші арқылы түсіндіруге тырысады. Осы деректер түрлерінің өлшемі сіздің құрылғыңызда әртүрлі болғандықтан, екі есе биттің кейбірі алынып тасталады және сіз көріп жатқан ел санымен аяқталады.

Бұл әрдайым бірдей болмауы мүмкін - дұрыс емес түрдегі көрсеткішке қол жеткізудің нәтижесі С тілінде анықталмаған, бірақ ол әлі де құрастырылуы мүмкін. C бағдарламашылары мұны анықталмаған мінез-құлық деп атайды (сіз C үйренгіңіз келсе, шынымен келісу керек фраза).

Сондай-ақ, printf деп аталатын кезде, оны форматтағы жолдан күтетін түрдің айнымалы мәндерін беруіңіз керек. Сондықтан егер сіз оны бірінші толтырғыш %. F болса, онда сіз керек , ол қосарланған бірінші дәлел беріңіз. Егер болмасаңыз, printf де анықталмаған мінез-құлыққа ие болады және ештеңе жасай алмайды (анықталмаған мінез-құлқын елге шығуы мүмкін, шағылысуы мүмкін немесе қарапайым нөмірді шығара аласыз ... ең нашар сәтке дейін ).

5
қосылды
@Bobby - жақсы ... түрі. Сонымен қатар, сіз не болатынын болжауға тырыспаңыз . Егер сіз өзіңіздің компиляторыңыз бен компьютеріңіз туралы жеткілікті білсеңіз, сіздің бағдарламаңыз іске қосылады, әдетте не болатынын айтуға болады. Бірақ бұл ақымақ ойын, және сіз портативті кодты ұстауыңыз керек.
қосылды автор detly, көзі
@Bobby - тек кейбір қосымша ақпарат: Көптеген компиляторларда жалпыға ортақ белгісіз мінез-құлық түрлері туралы ескертетін жалаулар бар; мысалы, gcc бар -Wall және clang бар -fcatch-undefined-behavior . Бірақ олар анықталмаған мінез-құлықтың белгілі бір жиынтығын табуға тырысады, және олар ешқашан мінсіз бола алмайды. Ең жақсы қорғаныс тілді жақсы меңгеру болып табылады және сіз елдегі мінез-құлық туралы сұрақ қоя отырып, С стандартына сілтеме жасайтын жауаптарды іздеңіз.
қосылды автор detly, көзі
@Bobby: Бұл мінез-құлықты болжауға ешқандай мүмкіндік жоқ; бұл стандартта мінез-құлықтың анықтамасы жоқ, сондықтан бағдарлама «дұрыс емес» және компилятор ештеңе істей алмайды - құжатты емес, не істеу керек екенін.
қосылды автор Jon Purdy, көзі
Рахмет. Сіз анықталмаған мінез-құлыққа сілтеме жасай отырып, сіз әлемде не шығаратыны туралы болжаудың ешқандай әдісі жоқ дегенді білдіресіз бе?
қосылды автор Bobby, көзі

Сіздің көрсеткіштеріңіз - int * . double -ге ауысуды қаласаңыз, оны double * болуы керек. Сіздің компиляторыңыз сізге сәйкес келмейтін көрсеткіш тапсырмасы туралы ескертуі керек.

2
қосылды

Сіздің көрсеткіштеріңіз - барлық int . Бұл дұрыс емес. Оларды ауыстырыңыз

int *ptra;
char *ptrb;
double *ptrc;
2
қосылды
Рақмет сізге! Өз тарапымнан ащы қате. Кешіріңіз :-)
қосылды автор Bobby, көзі

көрсеткішінің деректер түріне сәйкес келуі үшін өзгерту қажет, сонда өлшем мөлшері тиісті түрде орнатылады.

char *ptrb;
double *ptrc;
1
қосылды

Тиісті түрдегі көрсеткішті жариялау керек.

int *ptra;
char *ptrb;
double *ptrc;
1
қосылды

Егер мен жазылған көрсеткіштер туралы бірнеше сөз айта аламын.

Түрі бар көрсеткіштер ( void * көрсеткішінен өзгеше) жадта қанша байтқа жететінін біледі. Мысалы, 32-биттік жүйе мен бүтін сан көрсеткіші тұтас мәндерді қамтитын массив арқылы иерация кезінде әдетте төрт байтқа жетеді.

Әрдайым 1 байттың C стандарты бойынша кепілдік беретін шар белгісі бір уақытта 1 байтқа жетеді.

Оны кішкене код үзіндісімен көрсетуге рұқсат етіңіз:

#include 

int main()
{
    char array [] = "This is a char array.";

    int* int_ptr;

    char* char_ptr;

    char_ptr = array; /* This is okay, we have a char array and we assign its address to a char pointer */

    int_ptr = array; /* It will complain but let's go along with it */

    printf("%p, %p, %p\n", array, char_ptr, int_ptr); /* They should all point to the same address in memory */

    printf("%p\n", ++char_ptr); /* it will have advanced by one byte */

    printf("%p\n", ++int_ptr); /* it will have advance by four bytes */    

    return 0;
}

Менің компьютерімде мынадай шығу бар:

$ ./a.out 
0xbf8b85d2, 0xbf8b85d2, 0xbf8b85d2
0xbf8b85d3
0xbf8b85d6

Көріп отырғанымыздай, олар біз болжағандай дамыды. Әрине, бұл барлық мәселелерді тудыруы мүмкін, біз өзіміздің көрсеткіштерімізді ажырата бастаған кезде және олардың негізгі түріне сәйкес келмейді.

void * көрсеткіштеріне қатысты оларда арифметика заңсыз .

0
қосылды

ptrc көрсеткіші varaible мекенжайына сілтеме жасайды, оның деректер түрі бүтін сан, бірақ сіз оны екі есе пайдаланасыз.

0
қосылды