Указатели программирования на C - PullRequest
0 голосов
/ 09 октября 2009

Я не понимаю, почему последний кодовый блок генерирует 1819043176 1870078063 6581362 0 1 2 3 4 0 6488159 ... Эти числа не случайны, но почему эти числа? Спасибо!

int main(void) {
    int x;
    int y[10];
    int* p;
    char* q;
    int k;
    char* prefix;

    k = 0;
    while (k < 10) {
            y[k] = k;
            k = k + 1;
    }
    x = 42;
    printf("address of y are %d %d %d\n", y, y + 1, y + 9);
    doit(y + 1);

    p = &y[0];
    printf("p is %d\n", p);
    *p = 42;
    p = p + 9;
    printf("p is %d\n", p);
    *p = 17;

    q = "hello world";
    p = "hello world";
    k = 0;
    while (k < 10) {
            printf("%d ", q[k]);
            k = k + 1;
    }
    printf("The end\n");

    k = 0;
    while (k < 10) {
            printf("%d ", p[k]);
            k = k + 1;
    }
    printf("The end\n");
}

пустяк

void doit(int p[9])
{
    char* prefix = "";
    int k = 0;
    printf("p is %d at address %d\n", p, &p);
    while (k < 10)
    {
        printf("%s%d", prefix, *p);
        prefix = ", ";
        k = k + 1;
        p = p + 1;
    }
    printf("\n");
}

Ответы [ 7 ]

5 голосов
/ 09 октября 2009

1819043176 - это 6C6C6568 в шестнадцатеричном формате, который сохраняется как байты 68, 65, 6c, 6c на машине с прямым порядком байтов. Это первые четыре персонажа "Привет, мир". И так далее.

Обычно вы не должны делать это в C, результаты не определены или зависят от реализации.

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

4 голосов
/ 09 октября 2009

Я недостаточно копаюсь, чтобы дать вам ответ, но у меня есть важное предложение: проверьте предупреждения вашего компилятора. Когда мой bash запускается, он псевдонимом gcc - /usr/bin/gcc -Wall -Wextra -Werror так что все, что я пытаюсь скомпилировать, должно пройти через некоторые из самых суровых тестов GCC (и все предупреждения воспринимаются как ошибки, поэтому незначительные ошибки не будут компилироваться). Ваш код дал мне распечатку ошибки длиной в милю (не буквально). Некоторые ошибки:

  • printf() имеет специальный спецификатор формата для указателей: %p. Не используйте %d - это для int с.
  • p - это int * (указатель на int), "hello world" - это char *. Вы можете назначить одно другому, но обычно это плохая идея, поэтому если вы действительно хотите сделать это, вы должны использовать приведение, чтобы сказать: "Эй, я хотел это сделать:" p = (int *) "hello world";
  • main() не возвращает void, возвращает int. Вы знаете это, потому что вы объявили int main(void) хорошим программистом, но затем мы подходим к концу main(), и нет заявления return! Как это должно вернуть int, если вы ничего не return? В C ++ мы можем пропустить завершающий оператор return, но не в C (по крайней мере, мы действительно не должны этого делать, потому что могут случиться плохие вещи).

Кроме того, у вас есть шаблон, который вы часто повторяете:

k = 0;
while (k < 10) {
        y[k] = k;
        k = k + 1;
}

Добро пожаловать в for петли:

for(k = 0; k < 10; k++) {
        y[k] = k;
}

for() петли состоят из трех частей:

for(init; cond; inc)

init выполняется один раз перед циклом, затем цикл выполняется до тех пор, пока cond имеет значение true, выполняя inc в конце каждого цикла. Это почти точно соответствует тому, что вы делаете, и более кратко.

2 голосов
/ 09 октября 2009

у вас есть p, указывающая на строку "hello world"
но вы определили p как указатель на целые числа, поэтому p выглядит так

p[0] = 'hell'
p[1] = 'o wo'
p[2] = 'rldx'
p[3] = 'xxxx'
p[4] = 'xxxx'
p[5] = 'xxxx'
p[6] = 'xxxx'
p[7] = 'xxxx'
p[8] = 'xxxx'
p[9] = 'xxxx'

where xxxx means you have not set this memory to anything.

lets look at p[0]
h=0x68
e=0x65
l=0x6c
l=0x6c

so you have the hexidecimal number 0x6c6c6568 which you can check is 1819043176

and so on
0 голосов
/ 09 октября 2009

Ваша проблема связана с переменной p. это int *, а размер целочисленной переменной составляет 4 байта (он может изменяться в зависимости от системы и компилятора), но sizeof (char) равен 1 байту

Строка "Привет, мир" - 12 байт 12 байт можно определить как 3 целых числа.

после этой строки

p = "hello world";

будет использоваться только 3 * 4 памяти p. (* массив точек p "y") Остальные из них будут нулевыми ...

0 голосов
/ 09 октября 2009

Это не то, что вы думаете (возможно, я надеюсь):

while (k < 10) {
        printf("%d ", q[k]);
        k = k + 1;
}

Подумайте, что такое q, что делает printf и что означает% d (подсказка, посмотрите на назначение q). Я бы также предложил включить вывод того, что вы ожидаете получить в результате, потому что из кода не очевидно, что вы на самом деле пытаетесь достичь (кроме распечатки указателей на целые, используя printf вместо целых).

0 голосов
/ 09 октября 2009

Я думаю, это потому, что вы передаете символ в printf, когда строка формата ожидает целое число. Попробуйте привести q [k] и p [k] к целым числам.

while (k < 10) {
        printf("%d ", (int)p[k]);
        k = k + 1;
}

Вызов printf () не является обычным вызовом функции, он использует varargs / stdargs, и в них функция должна распаковать правильный тип.

Таким образом, первое число в вашем выводе, 1819043176, соответствует 0x6C6C6568. Посмотрите, как символьное значение для строчной буквы «h» (0x68), которое вы предположительно ожидали увидеть, является наименее значимым байтом в четырехбайтовом целом числе? Это потому, что подпрограммы varargs ожидали целочисленного аргумента из-за спецификатора формата% d.

0 голосов
/ 09 октября 2009

Причина того, что (а) вы печатаете числа и (б) числа не случайны, заключается в том, что в последнем блоке кода вы пытаетесь вывести строку в виде десятичных дробей. В конце концов, это то, что% d ожидает напечатать - десятичное число. Это не имеет ничего общего с указателями.

Вы не говорите, какой вывод вы ожидаете, но вы должны выбрать правильный форматер, чтобы сделать это.

Еще одно предложение - нормальная идиома для приращения переменной в C и C ++:

++x;

или

x++;

для увеличения значения на 1 и

x += 9;

чтобы увеличить его более чем на 1 (в данном случае, очевидно, на 9).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...