C: путаница с указателем - PullRequest
1 голос
/ 30 мая 2011

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

Программа 1:

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

int main()
{
 int a=1,b=2,c;
 c=(a+b)++;
}

Почему вывод ошибки? Требуемое значение?

Программа 2:

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

int main()
{
 char *p1="name";
 char *p2;

 p2=(char*)malloc(20);
 memset(p2,0,20);

 while(*p2++=*p1++);
 printf("%s\n",p2);

}

Почему вывод - пустая строка? И если я изменяю порядок приращения, то есть: while(++*p2=++*p1);, почему значение lvalueошибка приходит?

Ответы [ 4 ]

8 голосов
/ 30 мая 2011

Для первого вопроса (a+b)++ означает «увеличить значение a+b на 1».

Вы не можете увеличить a+b, поскольку это не переменная. Что бы вы ожидали в следующем коде?

int a = 1, b = 2;
printf("a = %d, b = %d, a+b = %d\n", a, b, a+b);
(a+b)++;
printf("a = %d, b = %d, a+b = %d\n", a, b, a+b);

Ясно, что первое printf должно напечатать

a = 1, b = 2, a + b = 3

А как насчет второго?

a =?, B =?, A + b = 4

Непонятно, какими должны быть a или b, если мы увеличиваем сумму.

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

Более простой способ сделать копию строки - использовать strcpy, вот так:

strcpy(p2, p1);

Обратите внимание, это безопасно только потому, что вы знаете, что размер строки в p1 не превышает размер p2. Если вы не уверены в размере строка (например, если вы получаете строку из пользовательского ввода), вам нужно быть осторожным, , как указано в Википедии .

Почему while(++*p2=++*p1); не работает, а while(*p2++=*p1++);:

Postfix- ++ имеет более высокий приоритет, чем *. Это означает, *p2++ означает *(p2++). Так

*(p2++) = something;

совпадает с

*p2 = something;
p2 += 1;

Между тем, ++*p2 означает ++(*p2), или «на что указывает p2 указывает, увеличено на единицу».

Опять вы получите проблему, если скажете:

 int a = 5, *p2 = &a;
 ++*p2 = 10;
 printf("a = %d\n", a);

Что вы ожидаете, что это напечатает? Во всяком случае, он должен вывести 9, потому что вы сообщаете компилятору, что *p2+1 = 10.

Вы не можете ожидать, что C-компилятор решит это уравнение, поэтому, чтобы язык был простым и эффективным, подобные вещи запрещены.

2 голосов
/ 30 мая 2011
c=(a+b)++;

a+b не является lvalue - как бы вы хотели присвоить что-либо результату добавления (rvalue) - и операторы ++ / - действительно назначают новое значение.

while(*p2++=*p1++);

Вы p2 указывает на \0 в конце строки.Вам нужно сохранить исходный адрес p2, на который указывает ваш цикл:

char *p3 = p2;
while(*p2++=*p1++)
    ;
printf("%s\n",p3);
1 голос
/ 03 октября 2011

Если вы посмотрите на цикл while:

while (* p2 ++ = * p1 ++);

помните, что выражение "True" в C, если оно не равно нулю, и false, если оно равно нулю.Несмотря на то, что цикл не имеет тела, поток управления по-прежнему:

проверка условия -> выполнение оператора в теле -> проверка условия

и здесь «условие проверки» означает «оценка»утверждение и посмотреть, если оно не равно нулю ".

Цикл while продолжает работать до тех пор, пока p1 не укажет на ноль, после чего управление переходит к printf.

например,

int main() 
{
    int array1[] = {2, 3, 1, 0, 3, 5};
    int array2[20];
    int * p2 = (int *)memset(array2, 0, 20*sizeof(int));
    int * p1 = array1;

    while(*p2++ = *p1++) {
        printf("In while: p1 is %d\n", *p1);
    }
    printf("Out of while: %d\n",*p2);
    return 0;

}

выход:

In while: p1 is 3
In while: p1 is 1
In while: p1 is 0
Out of while: 0
1 голос
/ 30 мая 2011
c=(a+b)++;

Оператор ++ не работает с временными переменными. (a+b) образует временный.

while(*p2++=*p1++);

Вы увеличиваете p2 здесь. После цикла p2 больше не указывает на начало блока памяти, возвращаемого последним вызовом malloc().

...