2016-05-26 2 views
1

Я знаю, что указатель одного типа может быть отлит в указатель другого типа, например, при использовании malloc указатель void может быть отлит другим типом. Но я видел этот фрагмент кода, который вводит значение непосредственно в тип указателя. Не могли бы вы помочь мне понять, что происходит?Литье типа указателя

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

enum otype {INT, SYM, CONS}; 
typedef struct obj { 
    enum otype type; 
    struct obj *p[1]; 
} obj; 

int 
main(void) 
{ 

    struct obj *o1 = (obj *) 10; 
    printf("%d\n", (int) o1); 

    struct obj *o2 = (obj *) "abc"; 
    printf("%s\n", (char *) o2); 

    return 0; 
} 
+1

Нет, вы не накладываете указатель 'void *' на другой тип. В этом-то и дело, почему 'malloc' возвращает' void * ', поэтому его можно назначить непосредственно на требуемый тип указателя. Также почему 'memcmp' принимает' void * 'аргументы, поэтому вы можете передать любой тип. –

+0

Что вы делаете с вашими призами, заключается в том, чтобы скрыть плохое использование указателей из компилятора. И какова цель одноэлементного массива 'struct obj * p [1];'? –

+0

Снова комментарий, размещенный ниже. \t Я думаю, что точка вышеприведенного кода заключается в том, что указатель не будет разыменован; скорее, это будет то, что obj может содержать перечисление типа INT, SYM и т. д., и массив внутри него будет указывать на (obj *) 10 или (obj *) "abc"; то позже эти значения могут быть восстановлены путем преобразования снова с использованием (int) или (char *). Вот как я это понимаю. Но я раньше не видел такого указателя, поэтому я спрашиваю о том, что происходит, и если я ошибаюсь или что-то не хватает – james0011

ответ

0

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

Указатель - это целое число, содержащее адрес памяти некоторого фрагмента данных. Когда вы бросаете его из одного типа в другой, то, что вы на самом деле делаете, говорит компилятору, что тот же номер (адрес памяти) относится к другому типу. В зависимости от типа источника и назначения, результат может варьироваться от полезного до полного и совершенно бессмысленного.

Берем пример:

struct obj *o1 = (obj *) 10; 

Это говорит компилятору для лечения адреса памяти 10 (0xa), как будто он содержит на структуру типа OBJ. Поскольку, по всей вероятности, адрес памяти 10 не содержит этого, пытаясь фактически разыменовать этот указатель, приведет к неопределенному поведению.

struct obj *o2 = (obj *) "abc"; 

Здесь мы находимся на более прочных основаниях (не так много). Это связано с тем, что, хотя мы не знаем, что такое адрес, который получил o2, мы знаем, что находится в этой памяти. Эта память содержит последовательность 0x61 0x62 0x63 0x00. Предполагая, что маленькая машина Endian (большая часть из которых в наши дни), это означает, что ваше перечисление содержит (недопустимое) значение 6513249, а ваш указатель так же неопределен, как и в первом случае.

+0

Привет, я думаю, что точка вышеприведенного кода заключается в том, что указатель не будет разыменован; скорее, это будет то, что obj может содержать перечисление типа INT, SYM и т. д.и массив внутри него будет указывать на (obj *) 10 или (obj *) "abc"; то позже эти значения могут быть восстановлены путем преобразования снова с использованием (int) или (char *). Вот как я это понимаю. Но я раньше не видел этого указателя, поэтому я спрашиваю, что происходит, и если я ошибаюсь или что-то не хватает. – james0011

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