KRS 0 28 июня, 2011 Опубликовано 28 июня, 2011 · Жалоба Так понятней? Да все было и так понятно! Не понятно зачем городить этот огород, не проще ли взять современный компилятор и объяснить ему что, где и в каком порядке лежит! Тогда код будет и понятнее и оптимальнее ;) потому что есть инструкции чтения с переворотом и т.п. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 0 28 июня, 2011 Опубликовано 28 июня, 2011 · Жалоба Так понятней? KRS все уже объяснил, почему делать так, как Вы сделали, неразумно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Petka 0 28 июня, 2011 Опубликовано 28 июня, 2011 · Жалоба Да все было и так понятно! Не понятно зачем городить этот огород, не проще ли взять современный компилятор и объяснить ему что, где и в каком порядке лежит! Тогда код будет и понятнее и оптимальнее ;) потому что есть инструкции чтения с переворотом и т.п. Прошу в студию код, как "правильно" объявить структуру blabla у ТС для gcc. KRS все уже объяснил, почему делать так, как Вы сделали, неразумно. Только что проверил. uint8_t msg[] __attribute__ ((aligned (16))) = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A }; struct blabla_t { char ch; int that __attribute__((packed)); } __attribute__((packed)); struct blabla_t *bla; int a; bla=&msg[3]; a = bla->that; printf("a = 0x%08X\n", a); bla=&msg[0]; a = bla->that; printf("a = 0x%08X\n", a); результат: a = 0x08070605 Ошибка шины Итог: никакие "#pragma packed" вам не помогут! Вот теперь понятно? P.S. Я включил в системе контроль alignment. "Ошибка шины" это "SIGBUS" - и есть ошибка невыровненного доступа. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KRS 0 28 июня, 2011 Опубликовано 28 июня, 2011 · Жалоба Итог: никакие "#pragma packed" вам не помогут! Вот теперь понятно? Ну вам не помогают, а мне помогают #include <stdint.h> #include <stdio.h> #pragma pack(1) typedef struct { char ch; int that; } blabla_t; #pragma pack() void test(blabla_t *bla) { printf("a = 0x%08X\n", bla->that); } uint8_t msg[] __attribute__ ((aligned (16))) = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A }; void test2(void) { blabla_t *bla; int a; bla= (blabla_t *)&msg[3]; a = bla->that; printf("a = 0x%08X\n", a); bla=(blabla_t *)&msg[0]; a = bla->that; printf("a = 0x%08X\n", a); } По листингу все читается по байтам, так что все ок! Все таки надо использовать typedef и при присваивании преобразовывать указатели, что бы не плодить warningи, на которые стоит обращать внимание! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Petka 0 28 июня, 2011 Опубликовано 28 июня, 2011 · Жалоба Ну вам не помогают, а мне помогают .... По листингу все читается по байтам, так что все ок! Все таки надо использовать typedef и при присваивании преобразовывать указатели, что бы не плодить warningи, на которые стоит обращать внимание! Давайте разбираться: Собрал ваш код gcc (4.5.2, "-O0"). Ошибка доступа ЕСТЬ! objdump -d -S ./a.out Вывод: 080483e3 <test2>: uint8_t msg[] __attribute__ ((aligned (16))) = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A }; void test2(void) { 80483e3: 55 push %ebp 80483e4: 89 e5 mov %esp,%ebp 80483e6: 83 ec 28 sub $0x28,%esp blabla_t *bla; int a; bla= (blabla_t *)&msg[3]; 80483e9: b8 20 a0 04 08 mov $0x804a020,%eax 80483ee: 83 c0 03 add $0x3,%eax 80483f1: 89 45 f4 mov %eax,-0xc(%ebp) a = bla->that; 80483f4: 8b 45 f4 mov -0xc(%ebp),%eax 80483f7: 8b 40 01 mov 0x1(%eax),%eax 80483fa: 89 45 f0 mov %eax,-0x10(%ebp) printf("a = 0x%08X\n", a); 80483fd: b8 20 85 04 08 mov $0x8048520,%eax 8048402: 8b 55 f0 mov -0x10(%ebp),%edx 8048405: 89 54 24 04 mov %edx,0x4(%esp) 8048409: 89 04 24 mov %eax,(%esp) 804840c: e8 e3 fe ff ff call 80482f4 <printf@plt> bla=(blabla_t *)&msg[0]; 8048411: c7 45 f4 20 a0 04 08 movl $0x804a020,-0xc(%ebp) a = bla->that; 8048418: 8b 45 f4 mov -0xc(%ebp),%eax 804841b: 8b 40 01 mov 0x1(%eax),%eax 804841e: 89 45 f0 mov %eax,-0x10(%ebp) printf("a = 0x%08X\n", a); 8048421: b8 20 85 04 08 mov $0x8048520,%eax 8048426: 8b 55 f0 mov -0x10(%ebp),%edx 8048429: 89 54 24 04 mov %edx,0x4(%esp) 804842d: 89 04 24 mov %eax,(%esp) 8048430: e8 bf fe ff ff call 80482f4 <printf@plt> } 8048435: c9 leave 8048436: c3 ret И где тут по-байтное обращение? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KRS 0 28 июня, 2011 Опубликовано 28 июня, 2011 · Жалоба Давайте разбираться: Собрал ваш код gcc (4.5.2). Ошибка доступа ЕСТЬ! И при чем здесь ARM? Интел умеет читать по не выравненному адресу, зачем читать по байтам? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Petka 0 28 июня, 2011 Опубликовано 28 июня, 2011 · Жалоба И при чем здесь ARM? Интел умеет читать по не выравненному адресу, зачем читать по байтам? Может, но не обязан. (См. eFlags, бит 18) И при чем здесь ARM? Да, проверил на ARM. Действительно читает по-байтно. P.S. Вот бы ещё ссылку на стандарт какой. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 0 28 июня, 2011 Опубликовано 28 июня, 2011 · Жалоба P.S. Вот бы ещё ссылку на стандарт какой. Причем тут стандарт? Что Вы хотите увидеть? Большими красными буквами "Компилятор языка 'C' обязан уметь корректно работать со структурами данных"? Есть структура данных, Вы полно и корректно описали, что она из себя представляет. Все, любой компилятор обязан правильно работать. Зачем указывать отдельно, например, в ГОСТ на автомобиль, то, что должен уметь перемещаться и без запряженной лошади? И уж тем более, не стоит ее в автомобиль запрягать, даже если в ГОСТ на него не написано, что лошадь не требуется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KRS 0 28 июня, 2011 Опубликовано 28 июня, 2011 · Жалоба Да, проверил на ARM. Действительно читает по-байтно. А хороший компилер, в случае с bla= (blabla_t *)&msg[3]; a = bla->that; должен читать сразу слово! (при соотв. уровне оптимизации) потому что в данном случае возможно проследить выравнивание. И, например, RVCT так и делает! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 29 28 июня, 2011 Опубликовано 28 июня, 2011 · Жалоба Если компилятор сам расположил структуру в памяти, то вне зависимости от директивы pack он должен корректно обращаться к памяти при доступе к любому полю. А вот если с указателями работать вольно, то запросто можно схлопотать ошибку доступа. Или вот так :) *((int *)0x40000007)=0; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться