2014-02-12 3 views
0

Предполагая, что вы не заботитесь о стиле литья компилятора и машины, есть ли заметная разница между:беззнаковое и Назад: Кастинг Указатель против Кастинг разыменовывают

#include <stdint.h> 
#include <inttypes.h> 
#include <stdio.h> 

static int64_t tosigned (void *p) 
{ 
    return *(int64_t *)p; 
} 

int main (void) 
{ 
    int64_t i = 0xfabf00d0badf00d; 
    uint64_t u = 0xabad1deacafebabe; 
    printf("%"PRId64 "\n" "%"PRId64 "\n", tosigned(&i), tosigned(&u)); 
    return 0; 
} 

И это?

#include <stdint.h> 
#include <inttypes.h> 
#include <stdio.h> 

static int64_t tosigned (void *p, int isunsigned) 
{ 
    return isunsigned ? (int64_t)*(uint64_t *)p : *(int64_t *)p; 
} 

int main (void) 
{ 
    int64_t i = 0xfabf00d0badf00d; 
    uint64_t u = 0xabad1deacafebabe; 
    printf("%"PRId64 "\n" "%"PRId64 "\n", tosigned(&i, 0), tosigned(&u, 1)); 
    return 0; 
} 

Ассамблея отвалов с использованием clang -S -std=c99 -Wall -Wextra для -O2 и выше показывают никакой разницы в мощности. Тем не менее, я хотел знать, был ли более «правильный» способ сделать это, или если первый метод будет работать в неопределенном или конкретном исполнении.

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

фон:

я писал библиотеку int64 для Lua и наткнулся на этом академический вопрос, когда делать для арифметики преобразования типов.

Я хранил int64_t и uint64_t userdata (непрозрачные C-кадры, хранящиеся во время выполнения Lua) в стеке Lua. Есть «метаметоды», назначенные для выполнения арифметики, например, "__add" для x + y вместо повышения ошибки типа, потому что вы не можете (как правило) выполнять арифметику по не номерам. Однако подписанные и неподписанные значения сохраняются как разные типы и, следовательно, несовместимы. Я делаю более широкое преобразование во втором аргументе, отбрасывая его на ту же подпись, что и первая. Параметр isunsigned примерно совпадает с «имеет ли это таблицу без знака?». Среда выполнения возвращает указатель void для сохраненного значения и то, как вы его конвертируете, зависит от вас.

+1

Я не думаю, что есть какая-то разница, но использование функции просто для кастинга кажется излишним. – Fernando

+0

Для библиотеки int64 для Lua см. Http://www.tecgraf.puc-rio.br/~lhf/ftp/lua/#lint64, но она поддерживает только подписанные номера. OTOH, арифметика в подписанных и неподписанных одинакова, это то, как они сравниваются и печатаются по-разному. – lhf

ответ

1

Первый метод, указатели на литье, разрешен стандартом C, поскольку C 2011 (N1570) 6.5 7 разрешает доступ к объекту с помощью подписанного или неподписанного типа, соответствующего эффективному типу объекта. То есть вам разрешено получить доступ к целому числу без знака как целое число со знаком такого же размера и наоборот. (Следует отметить, что это сглаживание является конкретным случаем, явно разрешенным стандартом C. Многие другие указатели указателей, за которыми следуют разыменования, будут нарушать правила псевдонимов, указанные в 6.5 7.)

Второй метод, целые числа со знаком, определяется стандартом C, если значение представляется в целевом типе (6.3.1.3 1) и определено в соответствии с другим (и может быть ловушкой) (6.3.1.3 3).

Смежные вопросы