sizeof (int) == sizeof (void *)?

Да, == плохо для сравнения строк (любые объекты действительно, если вы не знаете, что они канонические). == просто сравнивает ссылки на объекты. .equals() тесты для равенства. Для строк часто они будут такими же, но, как вы обнаружили, это не гарантируется всегда.

13
задан 2 February 2009 в 10:45
поделиться

11 ответов

Согласно эта страница Wikipedia, в C99 Ваш stdint.h заголовок мог бы объявлять intptr_t и uintptr_t, но затем это, конечно, требует

  • C99
  • конструктор компилятора А, который принял решение реализовать эту дополнительную часть стандарта

Так в целом, я думаю, что этот жесток.

16
ответ дан unwind 2 February 2009 в 20:45
поделиться
  • 1
    Как предложенный Jared, лучший способ шпионить за этими проблемами при помощи окна Modules (Отладчик-> Windows-> Модули) проверять DLL, который загружается, - действительно то, которое Вы просто создаете - проверяют это путем рассмотрения DLL' s дата в последний раз изменяется. Что-то, что работает отлично для меня при наличии подобных проблем, должно использовать Все ( voidtools.com , бесплатный инструмент that' s необходимость для программистов) для поиска имени DLL и вида, по дате Измененного. You' ре, вероятно, для нахождения и пути DLL, где это было просто восстановлено, и путь устаревшей копии DLL приложение, загружается. – Omer Raviv 11 January 2011 в 05:16

Стандарт C99 определяет стандартные международные типы:

7.18.1.4 Целых типа, способные к содержанию объектных указателей, следующий тип определяет тип целого числа со знаком со свойством, что любой допустимый указатель на пустоту может быть преобразован в этот тип, затем преобразовал назад в указатель на пустоту, и результат выдержит сравнение равный исходному указателю:

    intptr_t

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

   uintptr_t

Эти типы являются дополнительными.

C99 также определяет size_t и ptrdiff_t:

типы

  ptrdiff_t

, который является типом целого числа со знаком результата вычитания двух указателей;

  size_t

, который является типом беззнаковых целых чисел результата sizeof оператора; и

архитектура, которую я видел, имеет максимальный размер объекта, равного целой памяти, таким образом, sizeof (size_t) == sizeof (пусто*), но я не знаю ни о чем, что оба портативно к C89 (который size_t) и гарантируемый быть достаточно большим (который uintptr_t).

13
ответ дан Pete Kirkham 2 February 2009 в 20:45
поделиться
  • 1
    IConvertible на самом деле имеет больше смысла (если Вы не планируете отформатировать число.) – dlev 23 September 2011 в 07:59

Стандартное решение этой проблемы состоит в том, чтобы записать небольшую программу, которая проверяет размеры всех международных типов (короткое целое, интервал, длинное целое) и сравнивает их с void*. Если существует соответствие, оно испускает часть кода, который определяет тип intptr. Можно поместить это в заголовочный файл и использовать новый тип.

просто включать этот код в процесс сборки (использующий make, например)

2
ответ дан Aaron Digulla 2 February 2009 в 20:45
поделиться

Это было бы верно в стандартной системе на 32 бита, но конечно, нет никаких гарантий, и Вы могли найти большую архитектуру, где это не верно. Например, распространенное заблуждение - то, что sizeof (интервал) на x86_64 был бы 8 (так как это - система на 64 бита, я предполагаю), который это не. На x86_64, sizeof (интервал) все еще 4, но sizeof (пусто*) равняется 8.

4
ответ дан Liedman 2 February 2009 в 20:45
поделиться
  • 1
    @dlev: Я не соглашаюсь - OP конкретно желает всего отформатировать. Учитывая, что типы могут легко реализовать IFormattable, но не IConvertible, и что отдельный метод в IFormattable является точно тем, который OP хочет назвать, я думаю, что IFormattable имеет больше смысла. – Jon Skeet 23 September 2011 в 08:11

Таким образом что относительно C++. Сделайте я должен перейти к длинам:

template <int BITS> struct int_traits_t;
template <> struct int_traits_t <16> {typedef uint16_t int_t;};
template <> struct int_traits_t <32> {typedef uint32_t int_t;};
template <> struct int_traits_t <64> {typedef uint64_t int_t;};
typedef int_traits_t <sizeof (void*) * 8>::int_t myintptr_t;

только для получения портативного целого числа размера указателя?

3
ответ дан Benjamin 2 February 2009 в 20:45
поделиться
  • 1
    @Jon На основе OP' s вопрос, похоже, что у него есть опыт с фактическим использованием IConvertible версия ToString(), который является, почему я упомянул его. Ваша точка хорошо взята, все же. – dlev 23 September 2011 в 11:28

Проще говоря, нет. Не гарантируемый на всей архитектуре.

Мой вопрос: почему? Если Вы хотите выделить тип, достаточно большой для хранения void*, лучшая вещь выделить (удивительно достаточно :-) void*. Почему там потребность соответствовать ему в int?

РЕДАКТИРОВАНИЕ: На основе Ваших комментариев к Вашему дублирующемуся вопросу Вы хотите сохранить специальные значения указателя (1,2,3) для указания на дополнительную информацию.

НЕТ!! Не делайте этого!! . Нет никакой гарантии, которые 1, 2 и 3 не совершенно допустимые указатели. Это может иметь место в системах, где Вы обязаны выравнивать указатели на 4-байтовых границах, но, так как Вы спросили обо всей архитектуре, я предполагаю, что у Вас есть мобильность как высокое значение.

Находят другой способ сделать это, это корректно. Например, используйте объединение (синтаксис из памяти, может быть неправильным):

typedef struct {
    int isPointer;
    union {
        int intVal;
        void *ptrVal;
    }
} myType;

Затем можно использовать isPointer 'булевскую переменную', чтобы решить, необходимо ли рассматривать объединение как целое число или указатель.

РЕДАКТИРОВАНИЕ:

, Если скорость выполнения имеет главное значение, то решением для определения типа является способ пойти. В основном необходимо будет определить целое число, которое Вы хотите для каждой платформы, на которой Вы хотите работать. Можно сделать это с условной компиляцией. Я также добавил бы в проверке на этапе выполнения, чтобы гарантировать, что Вы скомпилировали для каждой платформы правильно таким образом (я определяю ее в источнике, но Вы передали бы это как флаг компилятора, как" cc -DPTRINT_INT"):

#include <stdio.h>
#define PTRINT_SHORT
#ifdef PTRINT_SHORT
    typedef short ptrint;
#endif
#ifdef PTRINT_INT
    typedef int ptrint;
#endif
#ifdef PTRINT_LONG
    typedef long ptrint;
#endif
#ifdef PTRINT_LONGLONG
    typedef long long ptrint;
#endif

int main(void) {
    if (sizeof(ptrint) != sizeof(void*)) {
        printf ("ERROR: ptrint doesn't match void* for this platform.\n");
        printf ("   sizeof(void*    ) = %d\n", sizeof(void*));
        printf ("   sizeof(ptrint   ) = %d\n", sizeof(ptrint));
        printf ("   =================\n");
        printf ("   sizeof(void*    ) = %d\n", sizeof(void*));
        printf ("   sizeof(short    ) = %d\n", sizeof(short));
        printf ("   sizeof(int      ) = %d\n", sizeof(int));
        printf ("   sizeof(long     ) = %d\n", sizeof(long));
        printf ("   sizeof(long long) = %d\n", sizeof(long long));
        return 1;
    }

    /* rest of your code here */

    return 0;
}

В моей системе (Ubuntu 8.04, 32-разрядная), я добираюсь:

ERROR: ptrint typedef doesn't match void* for this platform.
   sizeof(void*    ) = 4
   sizeof(ptrint   ) = 2
   =================
   sizeof(short    ) = 2
   sizeof(int      ) = 4
   sizeof(long     ) = 4
   sizeof(long long) = 8

В этом случае, я знал бы, что должен был скомпилировать с PTRINT_INT (или долго). Может быть способ поймать это во время компиляции с #if, но я не мог быть побеспокоен, исследовав его в данный момент. При нанесении удара платформы, где нет никакого целого типа, достаточного для содержания указателя, Вам не повезло.

Имеют в виду, что использование специальных значений указателя (1,2,3) для представления целых чисел не может также работать над всеми платформами - это может на самом деле быть действительными адресами памяти для указателей.

однако, если Вы собираетесь проигнорировать мой совет, нет очень, я могу сделать для остановки Вас. Это - Ваш код, в конце концов, :-). Одна возможность состоит в том, чтобы проверить все Ваши возвращаемые значения от malloc и, если Вы добираетесь 1, 2 или 3, просто malloc снова (т.е. имейте mymalloc (), который делает это автоматически). Это будет незначительной утечкой памяти, но она не гарантирует столкновений между Вашими специальными указателями и реальными указателями.

14
ответ дан paxdiablo 2 February 2009 в 20:45
поделиться
  • 1
    Отладчик-> Windows-> Модули работали на меня - мои DLLs оказывались в странном месте из-за недавних изменений в их проектах другой команды, и брались некоторые более старые версии DLLs. – Galadrius Krunthar 28 March 2013 в 11:03

Нет, самое близкое, Вы приедете в портативный способный к указателю целый тип, было бы intptr_t и ptrdiff_t.

1
ответ дан Ronny Vindenes 2 February 2009 в 20:45
поделиться
  • 1
    Та часть делает sens мне, но я могу также сделать что-то вроде этого: new Thread(() => _Transaction_Finalize_Worker(transId, machine, info, newConfigPath)).Start(); - почему я могу теперь передать во всех этих параметрах? – jocull 31 July 2011 в 14:09

Нет.

я не полагаю, что стандарт C даже указывает стандартные международные размеры . Объединение, что со всей архитектурой там (8/16/32/64bit и т.д.) и нет никакого способа гарантировать что-либо.

0
ответ дан Rob McCready 2 February 2009 в 20:45
поделиться

Ответ, кажется, "нет", но если все, в чем Вы нуждаетесь, является типом, который может действовать как оба, можно использовать объединение:

union int_ptr_t {
    int i;
    void* p;
};
0
ответ дан Magnus Hoff 2 February 2009 в 20:45
поделиться
  • 1
    Я предполагаю, что это - самая запутывающая часть. Я don' t добираются, как лямбда внезапно предоставляет доступ к внешним переменным объема. Есть ли что-либо больше к нему, чем " that' s просто путь это is"? – jocull 31 July 2011 в 14:12

тип данных int был бы ответом на большей части архитектуры.

, Но thre НИКАКОЙ гарантия к этому для ЛЮБОЙ (микро) архитектура.

0
ответ дан AlexDrenea 2 February 2009 в 20:45
поделиться

Обычно sizeof (*void) зависит от ширины шины памяти (хотя не обязательно - pre-RISC AS/400 имел 48-разрядную адресную шину, но 64-разрядные указатели), и интервал обычно является столь же большим как регистр ЦП общего назначения (существуют также исключения - SGI C, использовал 32-разрядный ints на 64-разрядном MIPS).

, Таким образом, нет никакой гарантии.

0
ответ дан qrdl 2 February 2009 в 20:45
поделиться
  • 1
    @jocull I' ve пытался описать, как лямбды работают в C# в моем ответе. – Ivan Danilov 31 July 2011 в 14:22
Другие вопросы по тегам:

Похожие вопросы: