2017-02-14 4 views
0

Я просматриваю код примера, в котором используется API, чтобы понять, как правильно использовать API. Я натолкнулся на какой-то код, который я сбила с толку. Ниже приведены соответствующие куски кода:последовательный перевод указателя в C

typedef struct myStruct_id{ 
randomStruct1 var1; 
void *var2; 
unsigned char *var3; 
randomStruct2 var4; 
int var5; 
}myStruct_name; 

//Function Prototype 
void randomFunction(const randomStruct1 *in1, const randomStruct2 *in2, void *handle); 

//Global Variables 
//assuming data1-5 are of the correct types corresponding to randomStruct1, void, etc. 
myStruct_name myStruct_var = {data1, data2, data3, data4, data5}; 
void *handle = (void*)myStruct_var; 

void main(){ 
    myStruct_name *local_var = (myStruct_name *)handle; 
    //Other code here 
    local_var.var2 = randomFunction(&local_var.var1, &local_var.var4, &(local_var)); 
} 

Я понимаю, что переменная ручка является нулевого общего указателя, указывающая на переменную myStruct_var (который был приведением типа как нуля родового указатель). В основной функции переменная local_var является указателем на struct myStruct_name, указывая на значение дескриптора указателя (которое вводится типа как указатель на тип myStruct_name), которое указывает на переменную myStruct_var. Далее функция randomFunction принимает в качестве входного указателя только для var1, указателя только на var2 и указателя на переменную local_var.

Моя путаница заключается в следующем: функция randomFunction требует в качестве входных указателей, указывающих на структуры и нулевой общий указатель а. Если local_var уже является указателем, зачем нужен адресный оператор (&)? Не является ли значение local_var уже адресом? Или мое понимание того, что происходит с local_var, неверно?

Кроме того, есть ли причина, по которой конечный вход в randomFunction заключен в скобки? То есть, почему это & (local_var), а не только & local_var? Скобки делают что-то?

Спасибо за чтение и любые ответы!

EDIT: Спасибо за ответы, указывающие, что я не имею в виду нулевой указатель. Я имею в виду void «тип данных» здесь как общий.

+0

Добро пожаловать в переполнение стека. Пожалуйста, найдите время, чтобы прочитать [The Tour] (http://stackoverflow.com/tour) и обратитесь к материалу из [Справочного центра] (http: // stackoverflow.com/help/ask), что и как вы можете задать здесь. –

+0

Я думаю, вы хотите прочитать концепцию * нулевого указателя * - Ваше использование этого звучит путано. – tofro

+1

_null pointer_ по определению указывает нигде. Просто объявляемый 'void *' не квалифицирует указатель как нулевой указатель. Сказал, что, зачем вообще игнорировать проверку типов? Не используйте 'void *' или casts без истинной необходимости. – Olaf

ответ

2

Если ваш фон находится на Java или каком-либо другом «безопасном» языке, указатели могут быть очень трудными обернуть голову. Но в основе вы просто имеете дело с памятью.

Первый вопрос - почему адрес указателя?

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

#include <stdio.h> 

typedef struct {int x; int y; int z;} XYZ; 

XYZ s1 = {1, 2, 3}; 
XYZ s2 = {4, 5, 6}; 

void swap1(XYZ *a, XYZ *b); 
void swap2(XYZ **a, XYZ **b); 

int main() 
{ 
    XYZ *p = &s1; 
    XYZ *q = &s2; 

    printf("Before\n"); 
    printf("Contents s1: %d %d %d s2: %d %d %d\n", s1.x, s1.y, s1.z, s2.x, s2.y, s2.z); 
    printf("Contents p: %d %d %d q: %d %d %d\n", p->x, p->y, p->z, q->x, q->y, q->z); 
    printf("Addresses: %p %p %p %p %p %p\n", &s1, &s2, p, q, &p, &q); 

    swap1(p, q); 

    printf("Swap 1\n"); 
    printf("Contents s1: %d %d %d s2: %d %d %d\n", s1.x, s1.y, s1.z, s2.x, s2.y, s2.z); 
    printf("Contents p: %d %d %d q: %d %d %d\n", p->x, p->y, p->z, q->x, q->y, q->z); 
    printf("Addresses: %p %p %p %p %p %p\n", &s1, &s2, p, q, &p, &q); 

    swap2(&p, &q); 

    printf("Swap 2\n"); 
    printf("Contents s1: %d %d %d s2: %d %d %d\n", s1.x, s1.y, s1.z, s2.x, s2.y, s2.z); 
    printf("Contents p: %d %d %d q: %d %d %d\n", p->x, p->y, p->z, q->x, q->y, q->z); 
    printf("Addresses: %p %p %p %p %p %p\n", &s1, &s2, p, q, &p, &q); 

    return 0; 
} 

void swap1(XYZ *a, XYZ *b) 
{ 
    XYZ *t; 
    t = a; 
    a = b; 
    b = t; 
} 

void swap2(XYZ **a, XYZ **b) 
{ 
    XYZ *t; 
    t = *a; 
    *a = *b; 
    *b = t; 
} 

При компиляции и запуска кода выше, вы получите что-то вроде этого:

Before                             
Contents s1: 1 2 3 s2: 4 5 6                       
Contents p: 1 2 3 q: 4 5 6                        
Addresses: 0x60103c 0x601048 0x60103c 0x601048 0x7ffd29c58288 0x7ffd29c58280           
Swap 1                             
Contents s1: 1 2 3 s2: 4 5 6                       
Contents p: 1 2 3 q: 4 5 6                        
Addresses: 0x60103c 0x601048 0x60103c 0x601048 0x7ffd29c58288 0x7ffd29c58280           
Swap 2                             
Contents s1: 1 2 3 s2: 4 5 6                       
Contents p: 4 5 6 q: 1 2 3                        
Addresses: 0x60103c 0x601048 0x601048 0x60103c 0x7ffd29c58288 0x7ffd29c58280 

Обратите внимание, что поменяться 1 ничего не делать, то только на своп 2, где адреса указателей, что произошло своп. Также обратите внимание, что s1 и s2 остались без изменений. Вы можете использовать эту функцию для реализации сортировки, которая не требует копирования целых структур.

Второй вопрос: Почему &(local_var) против &local_var?

Различия не являются функционально значимыми. Возможно, это был остаток предыдущего выражения, вырезанный & пастой, что угодно. Множество причин.

+0

Спасибо Yimin! Просто чтобы забить дом, я понимаю. local_var IS указатель и использование оператора адреса (&) с local_var передает адрес связанного local_var функции randomFunction? Независимо от того, что делает эта функция, ей передаются данные «адрес указателя»? – MCHatora

+0

Правильно, 'local_var' является указателем на структуру, а' & local_var' является адресом указателя на структуру. –