Точки, които трябва да се имат предвид при писане на код, който е преносим както към 32, така и към 64 битови архитектури

Кои са моментите, които трябва да имате предвид, докато пишете код, който трябва да бъде преносим както на 32-битови, така и на 64-битови машини?

Мислейки повече за това, смятам, че ако можете да добавите опита си относно проблемите, с които се сблъсквате, това ще помогне.

Като добавим още към това, веднъж се сблъсках с проблем поради липсващ прототип за функция, която връщаше връщане на указател. Когато пренесох същото на 64-битова машина, кодът се срива и нямах представа за причината от известно време, по-късно разбрах, че се предполага, че всички липсващи прототипи връщат int, причинявайки проблема.

Всички подобни примери могат да помогнат.

РЕДАКТИРАНЕ: Добавяне към уикито на общността.


person Community    schedule 12.02.2010    source източник
comment
вижте stackoverflow.com/questions/411798/   -  person Christoph    schedule 12.02.2010
comment
и stackoverflow.com/questions/534941/   -  person lsalamon    schedule 12.02.2010


Отговори (5)


Имам проблеми:

  1. Прехвърлянето на указатели към цели типове е опасно
  2. Размерите на структурата на данните могат да се променят
  3. Внимавайте за разширението на знака
  4. Различен ABI?

Някои съвети и трикове, които намерих за полезни:

  1. Снабдете се с целочислен тип с естествен размер (от заглавка или typedef ваш собствен) и го използвайте, когато имате променливи, които не се интересуват от размера.
  2. Използвайте изрични типове променливи, когато е възможно (u_int64_t, int_32_t и т.н.)
person Carl Norum    schedule 12.02.2010

  • Някои интегрални типове могат да имат различни размери
  • Указателите са с различна дължина
  • Подложка на структурата
  • Подравняване

В Windows има само конвенция за извикване на x64, за разлика от множественото на обикновена x32 машина.

Нещата стават по-мътни, когато имате някои компоненти, които са 32-битови и някои 64-битови. В Windows в крайна сметка написах COM услуга, за да ги накарам да говорят.

person dirkgently    schedule 12.02.2010

Натискането на указатели върху стека заема два пъти повече място. Въпреки това размерът на стека може да не се променя между версиите на операционната система, което води до мистериозен отказ на код, който работи добре в 32-битова версия, когато се компилира и работи непроменен на 64-битова. Не ме питайте откъде знам това.

person No Refunds No Returns    schedule 12.02.2010
comment
Никога не съм чувал за този. Това наистина ли влияе? - person Jay; 12.02.2010
comment
Това е вярно само когато компилаторът не може/не съхранява указателите в регистрите. - person philant; 30.04.2010

sizeof(int) може != sizeof(void*)

подравняване. Възможно е нуждите от подравняване да се променят. Това може да разкрие грешки, при които сте се отнасяли неправилно към неща, които е трябвало да бъдат подравнени, но са били подравнени само случайно в 32 бита (или на процесор, който не го интересува)

не предавайте 0 във varargs, ако приемникът очаква указател. Това е болезнено в C++, където опитните разработчици знаят, че 0 е валиден нулев указател. C dev обикновено ще използва NULL, така че вероятно сте добре

person pm100    schedule 12.02.2010
comment
+1 Сега се чудя дали това поведение е съвместимо. Стандартът казва, че NULL се оценява на 0. Не трябва ли да бъде повишен до (void*) по подразбиране? Не че не трябва да използвате NULL, но като четете стандарта, авторите на заглавки биха могли също така да дефинират NULL като 0. open-std.org/JTC1/SC22/wg14/www/docs/n1425.pdf Вижте точка 3 на 6.3.2.3. Изглежда, че GCC е грешен или ще бъде грешен, след като това стане текущият стандарт. - person ; 13.02.2010
comment
gcc преобразува NULL в nullptr в моя случай. Така че проработи. Съгласен съм, че ако NULL беше дефинирано като 0, това нямаше да поправи грешката ми, в този случай ще трябва изрично да кажа (void*)0 - person pm100; 13.02.2010

Пишете автоматизирани тестове и ги изпълнявайте редовно и на двете платформи.

person Jesse Weigert    schedule 12.02.2010