C арифметические задачи с указателями - PullRequest
0 голосов
/ 15 августа 2011

У меня есть небольшая скрипка с арифметикой указателей и просто указатель в целом, и я собрал этот код.

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

int main(int argc,char **argv){
    void *ptr=NULL;
    char a='a';
    int i0=0;
    char b='b';
    int i1=1;
    char c='c';
    int i2=2;
    ptr=&a;
    //What do I do here to get to i0?
    printf("%d",(int*)ptr); //and to print it out?
    while(1);
    return 0;
}

Мой вопрос - именно то, что я положил в комментарии.Как заставить ptr указывать на i0, не выполняя 'ptr = & i0;'используя указатель арифметики?Также, как мне тогда правильно распечатать его для символов и целых чисел (один метод для char и один для int).

Заранее спасибо.;)

Ответы [ 8 ]

6 голосов
/ 15 августа 2011

Способ только для получения указателя на местоположение i0 - & i0.

Хотя некоторые компиляторы могут выравнивать i0, чтобы можно было использовать * ((int*) (((char*) ptr) - 1))для доступа i0, это не гарантировано.Компиляторы часто переупорядочивают локальные переменные или вообще не сохраняют их в памяти.

1 голос
/ 15 августа 2011

Вы можете выполнять арифметику указателей только внутри целого объекта (например, массива).Это работает:

#include <stdio.h>
int main(void) {
    int arr[100];
    int *ptr;
    arr[42] = 42;
    ptr = arr; /* ptr points to the 1st element */
    printf("%d\n", *(ptr + 42)); /* contents of the 43rd element */
    return 0;
}
1 голос
/ 15 августа 2011

Вы не можете сделать это.

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

Вы не можете сделать арифметику указателя для указателя на переменную и заставить его указывать на другую несвязанную переменную.

1 голос
/ 15 августа 2011

Ваш код не имеет смысла.У вас нет гарантии того, где a, i0, b, i1, c и i2 определены в памяти при их создании, поэтому вы не можете использовать арифметику указателей для перехода от адреса a (ptr = & a) к i0.

Если вы хотите, чтобы ptr соответствовал местоположению i0, вы можете сделать ptr = & i0.Если i0 было целым числом (которое оно есть), оно будет иметь размер 4 байта, поэтому вы можете использовать арифметику указателя для перемещения по этому целому числу 1 бит за раз, если указатель равен void / char.

1 голос
/ 15 августа 2011

Вы не можете заставить ptr указать на i0, используя арифметику указателя.Арифметика указателей работает только в пределах одного объекта массива (переменные, не являющиеся массивами, обрабатываются как массивы размера 1).Вы не можете использовать арифметику указателей, чтобы заставить указатель пропускать с одного автономного объекта на другой.

0 голосов
/ 15 августа 2011

Вам придется сделать что-то вроде этого:

int main(void)
{
    union u
    {
       char ch;
       int i;
    } arr[] = { { .ch = 'a' }, { .i = 0 }, { .ch = 'b' }, { .i = 1 } };

    union u *ptr = &arr[0];
    printf("%d\n", ptr[1].i);
}

Не совсем то, что вы написали, но сработало бы.

0 голосов
/ 15 августа 2011

единственное, о чем я могу думать, это:

ptr += ((char*)&i0 - &a)

, но не уверен, что он все равно действителен и не имеет большого значения от ptr = &i0

как отмечали другие, в соответствии со стандартом вы можете выполнять арифметику указателей только в пределах одного объекта, например структуры или массива, поэтому приведенный выше код, даже если он может работать, не совсем корректен

0 голосов
/ 15 августа 2011

В этом примере кода, не делая

ptr=&i0;

Вы не можете заставить ptr указать на i0 переносимо , потому что,
i0 - это просто локальная переменная, и ее адрес не сохраняется ни в одной другой переменной.

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