Понимание C: указатели и структуры - PullRequest
0 голосов
/ 01 марта 2011

Я пытаюсь лучше понять c, и мне трудно понять, где я использую символы * и &.И просто структура в целом.Вот немного кода:

void word_not(lc3_word_t *R, lc3_word_t A) {
    int *ptr;
    *ptr = &R;
    &ptr[0] = 1;
    printf("this is R at spot 0: %d", ptr[0]);
}  

lc3_word_t - это структура, определенная так:

struct lc3_word_t__ {
  BIT b15;
  BIT b14;
  BIT b13;
  BIT b12;
  BIT b11;
  BIT b10;
  BIT b9;
  BIT b8;
  BIT b7;
  BIT b6;
  BIT b5;
  BIT b4;
  BIT b3;
  BIT b2;
  BIT b1;
  BIT b0;
};

Этот код ничего не делает, он компилируется, но как только я его запускаю, я получаюОшибка «Ошибка сегментации».Я просто пытаюсь понять, как читать и писать в структуру и используя указатели.Спасибо:)


Новый код:

void word_not(lc3_word_t *R, lc3_word_t A) {
    int* ptr;
    ptr = &R;
    ptr->b0 = 1;
    printf("this is: %d", ptr->b0);
}

Ответы [ 5 ]

8 голосов
/ 01 марта 2011

Вот краткое изложение указателей (по крайней мере, я их использую):

int i;
int* p; //I declare pointers with the asterisk next to the type, not the name;
        //it's not conventional, but int* seems like the full data type to me.

i = 17; //i now holds the value 17 (obviously)
p = &i; //p now holds the address of i (&x gives you the address of x)
*p = 3; //the thing pointed to by p (in our case, i) now holds the value 3
        //the *x operator is sort of the reverse of the &x operator
printf("%i\n", i); //this will print 3, cause we changed the value of i (via *p)

И в паре со структурами:

typedef struct
{
    unsigned char a;
    unsigned char r;
    unsigned char g;
    unsigned char b;
} Color;

Color c;
Color* p;

p = &c;     //just like the last code
p->g = 255; //set the 'g' member of the struct to 255
            //this works because the compiler knows that Color* p points to a Color
            //note that we don't use p[x] to get at the members - that's for arrays

И, наконец, с массивами:

int a[] = {1, 2, 7, 4};
int* p;

p = a;    //note the lack of the & (address of) operator
          //we don't need it, as arrays behave like pointers internally
          //alternatively, "p = &a[0];" would have given the same result

p[2] = 3; //set that seven back to what it should be
          //note the lack of the * (dereference) operator
          //we don't need it, as the [] operator dereferences for us
          //alternatively, we could have used "*(p+2) = 3;"

Надеюсь, что это прояснит некоторые вещи - и не стесняйтесь спрашивать более подробную информацию, если есть что-то, что я пропустил.Ура!

3 голосов
/ 01 марта 2011

Я думаю, что вы ищете общий учебник по Си (которых много). Просто проверьте Google. На следующем сайте есть хорошая информация, которая лучше объяснит ваши вопросы.

http://www.cplusplus.com/doc/tutorial/pointers/
http://www.cplusplus.com/doc/tutorial/structures/

Они помогут вам с базовым синтаксисом и пониманием, что такое операторы и как они работают. Обратите внимание, что сайт на C ++, но его основы такие же, как и в C.

2 голосов
/ 01 марта 2011

Прежде всего, ваша вторая строка должна давать вам предупреждение о преобразовании указателя в int. Третья строка меня удивляет, компилируется вообще. Скомпилируйте на самом высоком уровне предупреждений и прислушайтесь к предупреждениям.

* делает разные вещи в зависимости от того, находится ли он в объявлении или выражении. В объявлении (например, int *ptr или lc3_word_t *R) это просто означает «это указатель».

В выражении (например, *ptr = &R) это означает разыменование указателя, которое, в основном, должно использовать указанное значение как обычную переменную.

& означает «принять адрес этого». Если что-то не является указателем, вы используете это, чтобы превратить это в указатель. Если что-то уже является указателем (например, R или ptr в вашей функции), вам не нужно снова брать его адрес.

1 голос
/ 01 марта 2011

Давайте пройдемся по коду.

Сначала вы объявляете указатель на int: int *ptr. Кстати, мне нравится писать это как int* ptr* рядом с int вместо ptr), чтобы напомнить себе, что указатель является частью типа, то есть тип ptr является указателем на int.

Далее вы назначаете значение, на которое указывает ptr, адрес R. * разыменовывает указатель (получает значение, на которое указывает), а & дает адрес. Это твоя проблема. Вы перепутали типы. Присвоение адреса R (lc3_word_t**) * ptr (int) не будет работать.

Далее &ptr[0] = 1;. Это не имеет большого смысла либо. &ptr[0] - это адрес первого элемента ptr (в виде массива). Я предполагаю, что вы хотите просто значение по первому адресу, то есть ptr[0] или *ptr.

1 голос
/ 01 марта 2011
int *ptr;
*ptr = &R;

Здесь ptr не инициализируется.Это может указывать на что угодно.Затем вы разыменовываете его с помощью * и назначаете ему адрес R.Это не должно компилироваться, поскольку &R имеет тип lc3_word_t** (указатель на указатель), в то время как *ptr имеет тип int.

&ptr[0] = 1; также недопустимо.Здесь вы берете адрес ptr[0] и пытаетесь присвоить его 1. Это также недопустимо, так как это значение, но вы можете подумать, что вы не можете изменить местоположение переменной ptr[0], поскольку вы по сутипытается сделать это изменение адреса ptr[0].

...