Re[6]: Умный вопрос по C/C++
От: CreatorCray  
Дата: 24.08.07 07:04
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Шахтер, Вы писали:


Ш>>
Ш>>    rol    ecx, 16                    ; 00000010H
Ш>>


E>А это точно быстрее обмена слов?

На большой куче процов будет медленнее...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: Умный вопрос по C/C++
От: Аноним  
Дата: 24.08.07 07:30
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, remark, Вы писали:


R>>А если sp не указывает на &(*arg), то куда ж ему ещё указывать?!

E>Да он скорее всего туда и указывает.
E>Просто остальные пользователи *arg могут не заметить твоих последующих усилий и прочитать всё раньше, чем ты запишешь, например

R>>Тут фактически UB идёт только при доступе к объекту через sp, а при создании и инициализации sp UB нет. Т.к. далее я могу привести reinterpret_cast'ом sp обратно к uint32_t и получать доступ только через uint32_t.

R>>[абстрагируемся на время от факта, что программа с UB имеет полностью недетерминированное поведение ]

E>1) Насколько я понимаю, то если ты приведёшь туда-сюда, то вообще не будет ничего плохого. Не понятен только смысл этой деятельности

E>2) UB вовсе не обозначает полностью недетерминированного поведения. Это всего лишь значит, что реализация может делать что угодно. Часто конкретная реализация имеет вполне известное и детерминированное и даже документированное поведение в случае каких-то UB
E>3) В частности, когда ты через хаки лазаешь в "кишки" большого типа, представляя его как коллекцию маленьких, стандарт ничего не гарантирует на тему последствий. Гарантировать может в такой ситуации реализация, железо, например.

Следует ли считать, что reinterpret_cast объявлен deprecated? В силу такого поведения компиляторов, использование reinterpret_cast полностью теряет смысл. Поскольку превращается в гадание на кофейной гуще.
Re: Умный вопрос по C/C++
От: Аноним  
Дата: 24.08.07 07:40
Оценка:
Здравствуйте, McSeem2, Вы писали:

MS>Это не глюк компилятора, компилятор ведет себя совершенно корректно. Просьба к гуру — подождать пару дней с ответом, чтобы любопытные, но менее опытные попытались сами докопаться до истины. А потом я хочу задать дополнительные вопросы, возникшие в связи с этим.


а может кто-нибудь сказать насколько данное использование reinterpret_cast правильно?


static bool is_not_valid_check_sum(const uint8_t* rec, size_t rec_len)
{
    if (rec_len < 3)
        return true;

    const uint8_t* sz_end = rec + rec_len - sizeof(uint16_t);
    uint16_t sum = 0;

    for (; rec < sz_end; ++rec)
        sum += *rec;

    return sum != *reinterpret_cast<const uint16_t *>(sz_end);
}


идея в том что в конце записи есть двухбайтовое поле содержащие checksum,
подсчитывается оно протым сложением байт записи.

ЗЫ код скорее всего надо будет портировать на arm, поэтому мнение людей работавших с
arm тоже очень и очень интересно?
Re[6]: Умный вопрос по C/C++
От: Аноним  
Дата: 24.08.07 07:42
Оценка:
Здравствуйте, Awaken, Вы писали:

A>пожалуй стоит привести асмовый код полностью

A>там с /O3 эта функция не вызывается — она инлайнится (тогда зачем компилятор оставил ее код?)

A>/O1

A>
A>    .file    "a.c"
A>    .text
A>.globl swap_words
A>    .type    swap_words, @function
A>swap_words:
A>    pushl    %ebp
A>    movl    %esp, %ebp
A>    movl    8(%ebp), %eax
A>    movzwl    2(%eax), %ecx
A>    movzwl    (%eax), %edx
A>    movw    %dx, 2(%eax)
A>    movw    %cx, (%eax)
A>    popl    %ebp
A>    ret
A>    .size    swap_words, .-swap_words
A>    .section    .rodata.str1.1,"aMS",@progbits,1
A>.LC0:
A>    .string    "%08X %08X\n"
A>    .text
A>.globl main
A>    .type    main, @function
A>main:
A>    leal    4(%esp), %ecx
A>    andl    $-16, %esp
A>    pushl    -4(%ecx)
A>    pushl    %ebp
A>    movl    %esp, %ebp
A>    pushl    %ecx
A>    subl    $36, %esp
A>    movl    $-65536, -8(%ebp)
A>    leal    -8(%ebp), %eax
A>    movl    %eax, (%esp)
A>    call    swap_words
A>    movl    -8(%ebp), %eax
A>    movl    %eax, 8(%esp)
A>    movl    $-65536, 4(%esp)
A>    movl    $.LC0, (%esp)
A>    call    printf
A>    movl    $0, %eax
A>    addl    $36, %esp
A>    popl    %ecx
A>    popl    %ebp
A>    leal    -4(%ecx), %esp
A>    ret
A>    .size    main, .-main
A>    .ident    "GCC: (GNU) 4.1.2 20061115 (prerelease) (SUSE Linux)"
A>    .section    .note.GNU-stack,"",@progbits
A>


A>/O3

A>
A>    .file    "a.c"
A>    .text
A>    .p2align 4,,15
A>.globl swap_words
A>    .type    swap_words, @function
A>swap_words:
A>    pushl    %ebp
A>    movl    %esp, %ebp
A>    movl    8(%ebp), %eax
A>    movzwl    2(%eax), %ecx
A>    movzwl    (%eax), %edx
A>    movw    %cx, (%eax)
A>    movw    %dx, 2(%eax)
A>    popl    %ebp
A>    ret
A>    .size    swap_words, .-swap_words
A>    .section    .rodata.str1.1,"aMS",@progbits,1
A>.LC0:
A>    .string    "%08X %08X\n"
A>    .text
A>    .p2align 4,,15
A>.globl main
A>    .type    main, @function
A>main:
A>    leal    4(%esp), %ecx
A>    andl    $-16, %esp
A>    pushl    -4(%ecx)
A>    pushl    %ebp
A>    movl    %esp, %ebp
A>    pushl    %ecx
A>    subl    $36, %esp
A>    movzwl    -6(%ebp), %edx
A>    movzwl    -8(%ebp), %eax
A>    movl    $-65536, -8(%ebp)
A>    movw    %dx, -8(%ebp)
A>    movw    %ax, -6(%ebp)
A>    movl    $-65536, 8(%esp)
A>    movl    $-65536, 4(%esp)
A>    movl    $.LC0, (%esp)
A>    call    printf
A>    addl    $36, %esp
A>    xorl    %eax, %eax
A>    popl    %ecx
A>    popl    %ebp
A>    leal    -4(%ecx), %esp
A>    ret
A>    .size    main, .-main
A>    .ident    "GCC: (GNU) 4.1.2 20061115 (prerelease) (SUSE Linux)"
A>    .section    .note.GNU-stack,"",@progbits
A>


Похоже, что подозрения подтвердились. Компилятор просто не использовал результат вычисления функции, а подставил исходную константу.
И кому только потребовалась такая оптимизация?
Re[2]: Умный вопрос по C/C++
От: Alexander Pazdnikov  
Дата: 24.08.07 08:05
Оценка:
Здравствуйте, Аноним, Вы писали:

А>    return sum != *reinterpret_cast<const uint16_t *>(sz_end);
А>}
А>


Если ядро ARM < 9, то часто будет получаться работа с невыровненной памятью.
На < ARM9 выравнивание до 4-х байт
На ARM9 выравнивание до 2-х байт.

Для проверки поробуй запустить вот этот тестик.

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>


void hex_print(uint8_t *buf, size_t size);

int main()
{

    

    uint8_t buf1[16], buf2[16], buf3[16];
    uint32_t val;
    uint16_t val16;
    
    memset(buf1, 0, sizeof(buf1));
    memset(buf2, 0, sizeof(buf2));
    memset(buf3, 0, sizeof(buf3));

    val = 0x11223344;
    val16 = 0x7799;
        
    *((uint32_t *)&buf1[0]) = val;
    *((uint32_t *)&buf2[2]) = val;
    *((uint32_t *)&buf3[1]) = val;
    
    *((uint16_t *)&buf1[8]) = val16;
    *((uint16_t *)&buf2[10]) = val16;
    *((uint16_t *)&buf3[9]) = val16;
    
    
    printf("buf1[0] = <%#X>, buf2[2] = <%#X>, buf3[1] = <%#X>\n",
        *((uint32_t *)&buf1[0]),
        *((uint32_t *)&buf2[2]),
        *((uint32_t *)&buf3[1])
    );
    
    printf("buf1[8] = <%#X>, buf2[10] = <%#X>, buf3[9] = <%#X>\n",
        *((uint16_t *)&buf1[8]),
        *((uint16_t *)&buf2[10]),
        *((uint16_t *)&buf3[9])
    );

    for(int i = 0; i < 16; i++){
        printf("%02i|", i);
    }
    printf("\n");

    hex_print(buf1, 16);
    hex_print(buf2, 16);
    hex_print(buf3, 16);
    
    return 0;
}

void hex_print(uint8_t *buf, size_t size)
{
    while(size-- > 0){
        printf("%02X ", *(buf++));
    }
    printf("\n");
}
Re[3]: Умный вопрос по C/C++
От: Аноним  
Дата: 24.08.07 08:15
Оценка:
Здравствуйте, Alexander Pazdnikov, Вы писали:

AP>Здравствуйте, Аноним, Вы писали:


AP>
А>>    return sum != *reinterpret_cast<const uint16_t *>(sz_end);
А>>}
А>>


AP>Если ядро ARM < 9, то часто будет получаться работа с невыровненной памятью.

AP>На < ARM9 выравнивание до 4-х байт
AP>На ARM9 выравнивание до 2-х байт.

предположительно ARM9,
но вопрос решения остался за рамкой,
надо писать так?

uint16_t valid_sum;
memcpy(&valid_sum, sz_end, sizeof(valid_sum));
return sum != valid_sum;
Re[3]: Умный вопрос по C/C++
От: Аноним  
Дата: 24.08.07 08:25
Оценка:
AP>Если ядро ARM < 9, то часто будет получаться работа с невыровненной памятью.
AP>На < ARM9 выравнивание до 4-х байт
AP>На ARM9 выравнивание до 2-х байт.

и еще вопросы (простите за наглость),
1)Какой coding style в связи с этим вы используете? типа никаких reinterpert_cast и т.д.
2)а на ARM9 подобных проблем быть не может, ну скажем если поменть тип checksum на какой-нибудь другой,
или складывать не побайтово, а по x-разрядных чисел?
3)а скажем packed структура, мне приходит поток байт
const uint8_t *data, size_t data_len;

а на самом деле это
unsigned some_number;
Foo foo;

где Foo:
struct Foo {
} __attribute__ ((packed));

и я делаю так:
Foo *p = reinterpret_cast<const Foo *>(data + sizeof(unsigned));

это тоже будет невалидно на ARM?
Re[4]: Умный вопрос по C/C++
От: Alexander Pazdnikov  
Дата: 24.08.07 08:29
Оценка:
Здравствуйте, Аноним, Вы писали:
А>предположительно ARM9,
А>но вопрос решения остался за рамкой,
А>надо писать так?

А>uint16_t valid_sum;
А>memcpy(&valid_sum, sz_end, sizeof(valid_sum));
А>return sum != valid_sum;
А>


#include <stdint.h>

#define SET_BUF8_VAL16(BUF_UINT8T__, VAL_UINT16T__) \
    { \
        (BUF_UINT8T__)[0] = ((uint8_t *)&(VAL_UINT16T__))[0]; \
        (BUF_UINT8T__)[1] = ((uint8_t *)&(VAL_UINT16T__))[1]; \
    }

#define SET_VAL16_BUF8(VAL_UINT16T__, BUF_UINT8T__) \
    { \
        ((uint8_t *)&(VAL_UINT16T__))[0] = (BUF_UINT8T__)[0]; \
        ((uint8_t *)&(VAL_UINT16T__))[1] = (BUF_UINT8T__)[1]; \
    }
#define SET_BUF8_VAL32(BUF_UINT8T__, VAL_UINT32T__) \
    { \
        (BUF_UINT8T__)[0] = ((uint8_t *)&(VAL_UINT32T__))[0]; \
        (BUF_UINT8T__)[1] = ((uint8_t *)&(VAL_UINT32T__))[1]; \
        (BUF_UINT8T__)[2] = ((uint8_t *)&(VAL_UINT32T__))[2]; \
        (BUF_UINT8T__)[3] = ((uint8_t *)&(VAL_UINT32T__))[3]; \
    }

#define SET_VAL32_BUF8(VAL_UINT32T__, BUF_UINT8T__) \
    { \
        ((uint8_t *)&(VAL_UINT32T__))[0] = (BUF_UINT8T__)[0]; \
        ((uint8_t *)&(VAL_UINT32T__))[1] = (BUF_UINT8T__)[1]; \
        ((uint8_t *)&(VAL_UINT32T__))[2] = (BUF_UINT8T__)[2]; \
        ((uint8_t *)&(VAL_UINT32T__))[3] = (BUF_UINT8T__)[3]; \
    }


Хотя и вариант с ротацией тоже использовал.

uint16_t valid_sum = sz_end | (sz_end << 8);
return sum != valid_sum;
Re[4]: Умный вопрос по C/C++
От: Alexander Pazdnikov  
Дата: 24.08.07 08:43
Оценка:
Здравствуйте, Аноним, Вы писали:
А>1)Какой coding style в связи с этим вы используете? типа никаких reinterpert_cast и т.д.
А>2)а на ARM9 подобных проблем быть не может, ну скажем если поменть тип checksum на какой-нибудь другой,
А>или складывать не побайтово, а по x-разрядных чисел?

Для надежности и переносимости между разными процами( в том числе и ARM, x86 )
лучше медленнее, но надежнее.
#include <vector>
typedef std::vector<uint8_t> BufferType;
typedef uint32_t CrcType; // обязательно беззнаковый, иначе получим вопросы знакорасширения типов.

CrcType Crc8Mod2CheckSum::calc(BufferType& rBuf, bool crc_included_fl)
{
    CrcType cs = 0xFF;

    if (crc_included_fl){
        BufferType::iterator it_end = rBuf.end() - getCrcLen();
    }
    
    for (BufferType::iterator it = rBuf.begin(); it != it_end; ++it){
        cs ^= *it;
    }

    cs &= 0xFF;

    return cs;
}


От reinterpert_cast и прочих cast'ов можно отказаться, возможное их применение только для работы с буферами под пакеты приема/передачи.

uint32_t GetLong(BufferType::iterator& it)
{
    uint32_t retval = 0;

    ///\bug проверить валидность итератора
    for (int shift = 24; shift >= 0; shift -= 8){
        retval |= *it << shift;
        ++it;
    }

    return __le32_to_cpu(retval);
}


Как видите, обхожусь без cast'ов

А>или складывать не побайтово, а по x-разрядных чисел?

Безопаснее побайтно. Тем более для телемеханики — надежность на первом месте.

А>а на самом деле это

А>unsigned some_number;
А>Foo foo;

А>где Foo:

А>struct Foo {
А>} __attribute__ ((packed));

А>и я делаю так:

А>Foo *p = reinterpret_cast<const Foo *>(data + sizeof(unsigned));

А>это тоже будет невалидно на ARM?

Это лучше спросить у людей, которые используют разнообразные хаки от gcc/g++.
Re[5]: Умный вопрос по C/C++
От: Alexander Pazdnikov  
Дата: 24.08.07 08:46
Оценка:
Кстати, группа функций __le32_to_cpu и прочие работают через ротацию, а это уже в ядре сделано, наверное есть причины не использовать разных хаков.
Re[5]: Умный вопрос по C/C++
От: remark Россия http://www.1024cores.net/
Дата: 24.08.07 08:49
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Следует ли считать, что reinterpret_cast объявлен deprecated? В силу такого поведения компиляторов, использование reinterpret_cast полностью теряет смысл. Поскольку превращается в гадание на кофейной гуще.


Нет.
Такое использование незаконно. Но остальные использования reinterpret_cast законны.
Например, ты можешь скастить указатель на объект в int, а потом обратно, и нормально с ним работать дальше.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Умный вопрос по C/C++
От: remark Россия http://www.1024cores.net/
Дата: 24.08.07 08:51
Оценка:
Здравствуйте, Erop, Вы писали:

E>2) UB вовсе не обозначает полностью недетерминированного поведения. Это всего лишь значит, что реализация может делать что угодно.


А разьве выделенное не то же самое?

E>Часто конкретная реализация имеет вполне известное и детерминированное и даже документированное поведение в случае каких-то UB


Ключевое слово выделено

E>3) В частности, когда ты через хаки лазаешь в "кишки" большого типа, представляя его как коллекцию маленьких, стандарт ничего не гарантирует на тему последствий. Гарантировать может в такой ситуации реализация, железо, например.


Здесь тоже


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Умный вопрос по C/C++
От: Alexander Pazdnikov  
Дата: 24.08.07 09:18
Оценка:
Здравствуйте, Аноним, Вы писали:

А>3)а скажем packed структура, мне приходит поток байт

А>const uint8_t *data, size_t data_len;

А>а на самом деле это

А>unsigned some_number;
А>Foo foo;

А>где Foo:

А>struct Foo {
А>} __attribute__ ((packed));

А>и я делаю так:

А>Foo *p = reinterpret_cast<const Foo *>(data + sizeof(unsigned));

А>это тоже будет невалидно на ARM?


Вообще здесь больше проблема переносимости и совместимости разного оборудования, в частности самым выжным обмен данными между little endian и big endian. Ваша структура struct Foo возможно коректно будет обрабатываться между одними типами (le -> le) и (be -> be), но при работе (le -> be) и (be -> le) протокол обмена будет работать некорректно, т.к. порядок слудования байтов на этих устройствах будет разный.
В этом случае необходимо применять __leXX_cpu /__cpu_leXX и __beXX_cpu/__cpu_beXX. Просто определиться с протоколом обмена и порядком следования байт в протоколе обмена (LE или BE). и тогда использовать одну из пар макросов.
Re[4]: Умный вопрос по C/C++
От: Аноним  
Дата: 24.08.07 10:00
Оценка:
Здравствуйте, Аноним, Вы писали:

AP>>Если ядро ARM < 9, то часто будет получаться работа с невыровненной памятью.

AP>>На < ARM9 выравнивание до 4-х байт
AP>>На ARM9 выравнивание до 2-х байт.

А>и еще вопросы (простите за наглость),

А>1)Какой coding style в связи с этим вы используете? типа никаких reinterpert_cast и т.д.
А>2)а на ARM9 подобных проблем быть не может, ну скажем если поменть тип checksum на какой-нибудь другой,
А>или складывать не побайтово, а по x-разрядных чисел?
А>3)а скажем packed структура, мне приходит поток байт
А>const uint8_t *data, size_t data_len;

А>а на самом деле это

А>unsigned some_number;
А>Foo foo;

А>где Foo:

А>struct Foo {
А>} __attribute__ ((packed));

А>и я делаю так:

А>Foo *p = reinterpret_cast<const Foo *>(data + sizeof(unsigned));

А>это тоже будет невалидно на ARM?


Если у вас ARM процессор работает в отдельном от x86 адресном пространстве, то все указатели, адреса буферов и т.п. ARM определяет сам. В таком случае динамическая память выделяется по правильно выравненной границе. В случае размещения буфера в стеке необходимо корректно задать ему тип, т.е. не uint8_t data[xxx];
а
struct {
  unsigned some_number;
  Foo foo;
} data;


Тогда можно пользоваться тем способом, как вы написали. (вопрос об aliasing-е не рассматриваем).
Что касается __attribute__ ((packed)), то это определяется компилятором. Он может сам сгенерировать код для доступа к невыравненным данным. Тогда действительно будет плотная упаковка. А может и не иметь такой возможности. Тогда структура будет иметь пустоты, т.е. смещения полей в структуре на ARM и x86 будут разными.
Re[2]: Умный вопрос по C/C++
От: Pavel Dvorkin Россия  
Дата: 24.08.07 10:15
Оценка:
Здравствуйте, Андрей Коростелев, Вы писали:

АК>Здравствуйте, McSeem2, Вы писали:


АК>Правило введенное в С99 и запрещающее создание алиаса объекта с типом отличного от типа объекта-оригинала (ISO/IEC 9899 6.5/7) поддерживается в gcc 3.4.1 и выше на уровнях оптимизации начиная со 2-го. В данном случе sp не будет являться корректным алиасом для объекта *arg, потому компилятор вправе сгенерировать код, при котором sp не указывает на &(*arg).


А, простите, как быть, если у меня два указателя показывают на один и тот же адрес, но один char*, а другой нечто вроде

typedef char (*PCHAR20)[20];

Иными словами, я трактую этот адрес как адрес символа, с одной стороны, и строки символов длины 20 — с другой. Классика, в общем,многомерные массивы...
With best regards
Pavel Dvorkin
Re[6]: Умный вопрос по C/C++
От: Аноним  
Дата: 24.08.07 10:25
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, Аноним, Вы писали:


А>>Следует ли считать, что reinterpret_cast объявлен deprecated? В силу такого поведения компиляторов, использование reinterpret_cast полностью теряет смысл. Поскольку превращается в гадание на кофейной гуще.


R>Нет.

R>Такое использование незаконно. Но остальные использования reinterpret_cast законны.
R>Например, ты можешь скастить указатель на объект в int, а потом обратно, и нормально с ним работать дальше.

R>


Польза от такой оптимизации минимальна. Практически во всех случаях изменения типа оптимизатору нельзя отбрасывать это. Поскольку просто так адрес объекта брать никто не будет, пусть даже и используя другой тип указателя.
Ох, чует мое сердце, что это нововведение принесёт больше беды, чем пользы.
Лучшее враг хорошего.
Re[3]: Умный вопрос по C/C++
От: remark Россия http://www.1024cores.net/
Дата: 24.08.07 10:25
Оценка: +1
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>А, простите, как быть, если у меня два указателя показывают на один и тот же адрес, но один char*, а другой нечто вроде


PD> typedef char (*PCHAR20)[20];


PD>Иными словами, я трактую этот адрес как адрес символа, с одной стороны, и строки символов длины 20 — с другой. Классика, в общем,многомерные массивы...



Выражение PCHAR20[0] имеет тип char& (char lvalue). И именно через него ты получаешь доступ к памяти. Так что в обоих случаях тип, через который ты получаешь доступ к памяти одинаковое. Так что всё законно.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: Умный вопрос по C/C++
От: Alexander Pazdnikov  
Дата: 24.08.07 10:26
Оценка:
А>Если у вас ARM процессор работает в отдельном от x86 адресном пространстве, то все указатели, адреса буферов и т.п. ARM определяет сам. В таком случае динамическая память выделяется по правильно выравненной границе. В случае размещения буфера в стеке необходимо корректно задать ему тип, т.е. не uint8_t data[xxx];

Это только в случае выделения памяти в куче или на стеке.
А если эти данные в буфере? Буфер будет выровнен, а начало структуры данных может и небыть.
Re[5]: Умный вопрос по C/C++
От: Erop Россия  
Дата: 24.08.07 11:03
Оценка:
Здравствуйте, remark, Вы писали:

E>>2) UB вовсе не обозначает полностью недетерминированного поведения. Это всего лишь значит, что реализация может делать что угодно.


R>А разьве выделенное не то же самое?

Нет, как только ты фиксируешь реализацию, так большинство UB становятся вполне детерминированными
Возможно я непонятно выражаюсь. Извини.

E>>Часто конкретная реализация имеет вполне известное и детерминированное и даже документированное поведение в случае каких-то UB

R>Ключевое слово выделено
Ну UB-то разные бывают. Просто стандарт снимает с себя ответсвенность за последствия. Но никто не обязывает реализацию тоже снимать с себя ответсвенность...

E>>3) В частности, когда ты через хаки лазаешь в "кишки" большого типа, представляя его как коллекцию маленьких, стандарт ничего не гарантирует на тему последствий. Гарантировать может в такой ситуации реализация, железо, например.

R>Здесь тоже
Ну, например, если железо фиксирует endian, то ты, читая int как коллекцию char получаешь уже вполне определённое поведение...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Умный вопрос по C/C++
От: Аноним  
Дата: 24.08.07 11:05
Оценка:
Здравствуйте, Alexander Pazdnikov, Вы писали:


А>>Если у вас ARM процессор работает в отдельном от x86 адресном пространстве, то все указатели, адреса буферов и т.п. ARM определяет сам. В таком случае динамическая память выделяется по правильно выравненной границе. В случае размещения буфера в стеке необходимо корректно задать ему тип, т.е. не uint8_t data[xxx];


AP>Это только в случае выделения памяти в куче или на стеке.

AP>А если эти данные в буфере? Буфер будет выровнен, а начало структуры данных может и небыть.

Может. Но в таком случае не получится описать такую структуру буфера.
Если буфер описан, например, так:
struct Foo {
  unsigned SomeData;
};

struct DataBuf {
  unsigned char Byte;
  Foo foo;
};

то смещение поля foo зависит от компилятора. Обычно оно будет кратно 4. Заставить разместить foo по смещению 1 не получится. Если все же нужен именно упакованный буфер и переставить местами поля нельзя, то обращаться к невыравненным полям нужно с помощью соответствующих функций или макросов. В таком случае макросы будут разными для разных платформ.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.