Как преобразовать адрес переменной int в переменную типа char в C? - PullRequest
1 голос
/ 28 октября 2010

У меня следующий код, но я получаю неправильный вывод. Кто-нибудь может сказать мне, почему вывод 10 B только и почему я не получаю A на выходе ??

#include<stdio.h>
#include<conio.h>
void main()
{
    int *p;
    char c,d;
    int i;

    clrscr();
    p=&i;
    *p=10;
    (char *)p=&c;
    *p=65;
    (char *)p=&d;
    *p=66;
    printf("%d%c%c",i,c,d);
    getch();
}

Ответы [ 6 ]

5 голосов
/ 28 октября 2010

Ваша программа вызывает неопределенное поведение, поэтому нет правильного или неправильного.В частности:

*p = 65;

записывает целое число в память, оставляя место только для char.C99 §6.5.3.2 / 4 (Операции с адресом и косвенной адресацией):

Если операнд имеет тип '' указатель на тип '', результат имеет тип '' тип ''.Если указателю было присвоено недопустимое значение, поведение унарного оператора * не определено.84)

p имеет указатель типа на int, поэтому *p имеет тип int.Однако p не является адресом действительного int объекта.

Кроме того, я считаю, что приведение в левой части назначения является недопустимым (GCC определенно так считает).

Я полагаю, что происходит то, что это выложено (увеличение адреса) как:

|i|i|i|i|d|c|p|p|p|p|

Это представляет байты, которые каждый занимает.Я рассмотрю то, что, по-моему, происходит:

p = &i;

|i|i|i|i|d|c|00|00|00|00|

Для простоты я предполагаю, что адрес i равен 0.

*p=10;

|10|0|0|0|d|c|00|00|00|00|

p=&c;

|10|0|0|0|d|c|05|00|00|00|

*p=65;

|i|i|i|i|d|65|00|00|00|00|

Обратите внимание, что изменение *p перезаписываетp.

p=&d;

|10|0|0|0|d|65|04|00|00|00|

*p=66;

|10|0|0|0|66|00|00|00|00|00|

Таким образом, сохранение до d заменяет c на NULL.Вышеприведенное применимо, если ваша машина имеет младший порядок байтов, имеет 4-байтовые числа и стек растет вверх (по направлению к младшим адресам).Анализ отличается, если у вас есть 2-байтовые числа, но основной вывод все еще применим.

Возвращение void также недопустимо, но это не имеет отношения.

3 голосов
/ 28 октября 2010

Утверждение (char *)p=&c; волшебным образом не превращает p в char * с этого момента.В следующей строке, *p=65;, вы все еще помещаете int в это место.

То же самое для (char *)p=&d; *p=66;.Теперь, когда вы вставляете почти два байта в один байт d, вы, вероятно, перезаписываете c на 0.

Вы можете обнаружить, что изменение *p = 66 на *((char*)p) = 66 дастВы, что вы хотите, вставка одного байта.

И, пожалуйста, обновите до gcc, если это возможно.Он стоит точно так же, как Turbo C, и лучше примерно в каждый способ.

1 голос
/ 28 октября 2010

Вы хотите использовать

p = (int *) &c;

но когда вы делаете

*p = 65

тогда скомпилированная программа поместит 65 в виде 4-байтового значения (при условии, что ваш int равен 4 байту) в память, где находится c. Он уничтожит еще 3 байта ... потому что c - это всего 1 байт, и вы помещаете в него 4 байта данных ... и мне интересно, будет ли какая-либо платформа жаловаться, поскольку c является символом, и может не быть на границе ... ... 1010 *

Вы, вероятно, хотите использовать

char *pChar = &c;
*pChar = 65;

Если вы хотите поэкспериментировать с помещением байта 65 в целое число i, вы можете использовать

pChar = (char *) &i;
*pChar = 65;

(char *) называется приведением - делая его указателем на символ.

0 голосов
/ 28 октября 2010

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

Некоторые подсказки:

  • правильный включаемый файл для стандарта C stdio.h
  • в C выражение (char*)p не является lvalue, означающее, что вы не можете назначить на это. (на это есть веские причины)
  • Даже если вам удастся назначить адрес от char до int указатель это вообще плохо идея. Не только потому, что вы будете в конечном итоге переопределить память, которая не "твой", но и из-за проблемы с выравниванием. Лучшее, что может случиться с вами в таком случае является bus error, чтобы сказать вам рано, что вы на неправильном пути
  • тип возврата main равен int
0 голосов
/ 28 октября 2010

Вы неправильно используете оператор приведения. Вы связываете персонажа с int *. Поэтому вы должны разыграть этот символ *, чтобы разрешить преобразование. Правильный код, как показано ниже:

int *p; char c,d; int i; 
p=&i; 
*p=10; 
p=(int *)&c; 
*p=65; 
p=(int *)&d; 
*p=66; 
printf("%d%c%c",i,c,d); 
0 голосов
/ 28 октября 2010

Я не смог скомпилировать вашу программу, она не соответствует стандарту ANSI. Вот исправленная версия, и она печатает "10AB":

#include<stdio.h>

int main()
{

int *p;
char *cp;
char c,d;
int i;
p=&i;
*p=10;
cp=&c;
*cp=65;
cp=&d;
*cp=66;
printf("%d%c%c\n",i,c,d);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...