Передача значений из пустого указателя - PullRequest
0 голосов
/ 22 апреля 2011

Может кто-нибудь сказать мне, что не так с этим кодом?

base - пустой указатель на группу floats
i является значением >1
size - это размер типа (в данном случае float - 4)

char *a = (char *)base;
char *temp = (char *)a + size * (i/2);
printf("%d: %d = ", i, temp);
memcpy(a + size * i , temp , size);
printf("%d\n", a + size * i);

Это вывод:

2: 136724 = 136728
3: 136724 = 136732
4: 136728 = 136736
6: 136732 = 136744
7: 136732 = 136748
8: 136736 = 136752

Ответы [ 3 ]

1 голос
/ 22 апреля 2011
char *a = (char *)base;
char *temp = (char *)a + size * (i/2);
printf("%d: %f = ", i, *(float *)temp);
memcpy(a + size * i , temp , size);
printf("%f\n", *(float *)(a + size * i));

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

Причина, по которой ваш код не работал, заключается в том, что вы печатали адреса, а не значения.

1 голос
/ 22 апреля 2011

Если бы a было void*, компилятор не позволил бы вам написать a + size*i (вы не можете делать арифметику указателей с неполными типами). Возможно, это не тот тип, о котором вы думаете.

Но почему вы думаете, что есть проблема? Левый столбец перемещается вдвое быстрее, чем правый столбец, и это ожидается, потому что вы делите на 2.

Вы понимаете, что печатаете адреса, а не копируемые значения, верно?

0 голосов
/ 22 апреля 2011

Не могли бы вы рассказать нам, чего вы пытаетесь достичь? Выглядит как домашнее задание, верно?

Язык C позволяет вам привести любой указатель к пустоте *, а затем привести его вернуться к исходному типу указателя, не теряя никакой информации. Что-нибудь иначе вы делаете с пустым указателем - плохая идея, хотя некоторые библиотечные функции (например, memcpy) все еще имеют void * по историческим причинам. Вот почему вам не нужно явное приведение для перехода от любого типа указателя к пустоте *.

Вы не можете смотреть на то, на что указывает пустота, пока не отбросите ее обратно правильный тип указателя. И будьте осторожны, когда вы делаете!

#include <stdio.h>
#include <memory.h>

/* It's a bad idea to pass Base as a void pointer,
   but that's what you said you have. */
void silly_function(void*base, int i, int size) {
    /* Using a char* that points to float, is an even worse idea!
        char *a = (char *)base;
        char *temp = (char *)a + size * (i/2);
        printf("%d: %d = ", i, temp);
        memcpy(a + size * i , temp , size);
        printf("%d\n", a + size * i); 
    **/

    /** Probably ought to have a big SWITCH statement here, based
        on the data type. sizeof() isn't a good way to do this...
        On many computers, sizeof(float)==sizeof(long), but that
        doesn't mean that a float* is the same as a long* !!!
        For now, I'm going to assume (as you did) that base points
        to an array of float. */

    /* I think you're trying to copy the first half of the array
       into the second half of the array! But that's easy. */
    float*firsthalf = (float*)base; 
    float*secondhalf = firsthalf + (i/2);

    /* Show some starting values. */
    printf("Before: %x --> %f, %x --> %f\n",
        firsthalf, *firsthalf, secondhalf, *secondhalf);

    /* Now do the copy */
    memcpy(secondhalf, firsthalf, (i/2)*(sizeof(float)));

    /* Now prove that it's been copied? */
    printf("After:  %x --> %f, %x --> %f\n",
        firsthalf, *firsthalf, secondhalf, *secondhalf);
}

int main() {
    /* This drives the test */
    float ary[10] = {
        1.1f, 2.2f, 3.3f, 4.4f, 5.5f,
        0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
    silly_function(ary, 10, sizeof(ary[0]));
    return 0;
}

В моей системе вывод

Before: 12ff38 --> 1.100000, 12ff4c --> 0.000000
After:  12ff38 --> 1.100000, 12ff4c --> 1.100000

Надеюсь, это поможет.

...