Да, ==
плохо для сравнения строк (любые объекты действительно, если вы не знаете, что они канонические). ==
просто сравнивает ссылки на объекты. .equals()
тесты для равенства. Для строк часто они будут такими же, но, как вы обнаружили, это не гарантируется всегда.
Согласно эта страница Wikipedia, в C99 Ваш stdint.h заголовок мог бы объявлять intptr_t и uintptr_t, но затем это, конечно, требует
Так в целом, я думаю, что этот жесток.
Стандарт 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
).
IConvertible
на самом деле имеет больше смысла (если Вы не планируете отформатировать число.)
– dlev
23 September 2011 в 07:59
Стандартное решение этой проблемы состоит в том, чтобы записать небольшую программу, которая проверяет размеры всех международных типов (короткое целое, интервал, длинное целое) и сравнивает их с void*. Если существует соответствие, оно испускает часть кода, который определяет тип intptr. Можно поместить это в заголовочный файл и использовать новый тип.
просто включать этот код в процесс сборки (использующий make
, например)
Это было бы верно в стандартной системе на 32 бита, но конечно, нет никаких гарантий, и Вы могли найти большую архитектуру, где это не верно. Например, распространенное заблуждение - то, что sizeof (интервал) на x86_64 был бы 8 (так как это - система на 64 бита, я предполагаю), который это не. На x86_64, sizeof (интервал) все еще 4, но sizeof (пусто*) равняется 8.
Таким образом что относительно 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;
только для получения портативного целого числа размера указателя?
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 (), который делает это автоматически). Это будет незначительной утечкой памяти, но она не гарантирует столкновений между Вашими специальными указателями и реальными указателями.
Нет, самое близкое, Вы приедете в портативный способный к указателю целый тип, было бы intptr_t
и ptrdiff_t
.
new Thread(() => _Transaction_Finalize_Worker(transId, machine, info, newConfigPath)).Start();
- почему я могу теперь передать во всех этих параметрах?
– jocull
31 July 2011 в 14:09
Нет.
я не полагаю, что стандарт C даже указывает стандартные международные размеры . Объединение, что со всей архитектурой там (8/16/32/64bit и т.д.) и нет никакого способа гарантировать что-либо.
Ответ, кажется, "нет", но если все, в чем Вы нуждаетесь, является типом, который может действовать как оба, можно использовать объединение:
union int_ptr_t {
int i;
void* p;
};
тип данных int был бы ответом на большей части архитектуры.
, Но thre НИКАКОЙ гарантия к этому для ЛЮБОЙ (микро) архитектура.
Обычно sizeof (*void) зависит от ширины шины памяти (хотя не обязательно - pre-RISC AS/400 имел 48-разрядную адресную шину, но 64-разрядные указатели), и интервал обычно является столь же большим как регистр ЦП общего назначения (существуют также исключения - SGI C, использовал 32-разрядный ints на 64-разрядном MIPS).
, Таким образом, нет никакой гарантии.