Почему я могу использовать указатель в качестве буфера для write (), но мне нужно использовать адрес указателей в качестве буфера для read ()? - PullRequest
1 голос
/ 25 февраля 2011

Я пытаюсь передать один символ из родительского процесса в дочерний процесс. Обычно это делается с помощью простой переменной, но я пробую это с указателем. Если это делается с помощью простой переменной (var), аргумент буфера для write () и read () равен &var, но когда я использую указатель (*ptr), аргумент для read () равен ptr и аргумент для write () равен &ptr.

Я новичок в C и не могу понять, почему это так.

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

int main(void) {

  char *chPtr;
  int fd[2];
  pid_t pid;

  char value = 'z';

  pipe(fd);
  pid = fork();

  if (pid) {     // Parent
    close(fd[0]);
    chPtr = &value;
    write(fd[1], chPtr, 1);
    close(fd[1]);
  }

  if (! pid) {   // Child
    close(fd[1]);
    read(fd[0], &chPtr, 1);
    printf("the result is %c\n", (int)chPtr);
    close(fd[0]);
  }
  return 0;
}

Ответы [ 2 ]

1 голос
/ 25 февраля 2011

Указатель делает то, что предлагает его имя, он указывает на область памяти. В случае read вы сохраняете значение в указателе, а не помещаете значение в местоположение, на которое он указывает. Фактически, используя оператор & для указателя, вы фактически создаете указатель на указатель. Вот почему явное приведение требуется для использования значения в printf.

Вместо этого вы должны установить указатель на адрес value, а затем использовать указатель как обычно:

chPtr = &value;
read(fd[0], chPtr, 1);
printf("the result is %c\n", value);

Более распространенным является использование массива байтов (то есть char []) вместо указателя или вместо этого выделение памяти в куче (см. Malloc).

1 голос
/ 25 февраля 2011

Ваша дочерняя реализация не делает то, что вы ожидаете. Хотя это работает, это действительно ошибка дизайна.

Функция read () считывает в буфер, выделенный вызывающей стороной. Поскольку вы передаете & chPtr для read (), вы используете память для указателя в качестве буфера, что работает, поскольку вы читаете только один символ, который помещается в память для указателя.

Обычно вы хотели бы что-то вроде:

if (! pid) {   // Child
    char buf[1];
    close(fd[1]);
    read(fd[0], buf, 1);
    printf("the result is %c\n", buf[0]);
    close(fd[0]);
}
...