vectores que punteros puntero matrices funciones ejemplo declaracion con aritmetica c pointers null variable-assignment

que - punteros y vectores en c



Un puntero C no ajustado no es nulo (3)

Estoy jugando con los indicadores C. Cuando compilo y ejecuto el siguiente código.

Ejemplo 1:

#include <stdio.h> int main() { int k; int *ptr; k = 555; if (ptr == NULL) { printf("ptr is NULL/n"); } else { printf("ptr is not NULL/n"); printf("ptr value is %d/n", *ptr); } printf("ptr address is %p/n", ptr); }

Obtengo el resultado:

ptr is not NULL ptr value is 1 ptr address is 0x7fff801ace30

Si no asigno un valor a k:

Ejemplo 2:

#include <stdio.h> int main() { int k; int *ptr; if (ptr == NULL) { printf("ptr is NULL/n"); } else { printf("ptr is not NULL/n"); printf("ptr value is %d/n", *ptr); } printf("ptr address is %p/n", ptr); }

Entonces la salida es como esperaba:

ptr is NULL ptr address is (nil)

Del mismo modo, si defino las variables fuera de la función:

Ejemplo 3:

#include <stdio.h> int k; int *ptr; int main() { k = 555; if (ptr == NULL) { printf("ptr is NULL/n"); } else { printf("ptr is not NULL/n"); printf("ptr value is %d/n", *ptr); } printf("ptr address is %p/n", ptr); }

Salida:

ptr is NULL ptr address is (nil)

En el primer ejemplo, donde ptr tiene una dirección y un valor, ¿se espera este comportamiento? Si es así, entonces:

  • ¿Por qué ptr tiene una dirección y valor?
  • ¿De dónde vienen estos, qué los establece?
  • ¿Cómo puedo definir correctamente los punteros nulos en el ámbito local y mantenerlos nulos hasta que esté listo para usar?

Estoy compilando con gcc en Ubuntu 12.04.04 en x64:

root@dev:~# gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.6/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion=''Ubuntu/Linaro 4.6.3-1ubuntu5'' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)

EDITAR

He numerado mis ejemplos anteriores para mayor claridad.

Con base en la respuesta de Dietrich, hice un poco de búsqueda y encontré esta pregunta: ¿Por qué las variables globales siempre se inicializan a ''0'', pero no a las variables locales? .


Las variables locales en C no se inicializan automáticamente, solo las variables globales se inicializan automáticamente.

int x; // 0 by default static int y; // 0 by default void function() { static int z; // 0 by default int w; // Not initialized! Could be anything! }

El valor de una variable no inicializada no está especificado . En la práctica, esto puede significar cosas diferentes.

  • Puede ser cero, si su compilador o tiempo de ejecución pone a cero la memoria antes de usarla.

  • Puede llenarse con un centinela como 0xdeadbeef o 0xeeeeeeee .

  • Puede contener basura de lo que fue último en esa ubicación de memoria particular. (Este enfoque es el más común).

Está utilizando GCC, que usa el tercer enfoque, por lo que está viendo basura de la última función para usar esa ubicación de memoria. Puede ejecutar el programa con Valgrind ( muy recomendado ), y probablemente escupirá mensajes de error para usar la memoria no inicializada, aunque no se garantiza que capture todos los errores.

La forma correcta de hacer las cosas

Una opción es inicializar explícitamente las variables locales si va a usarlas.

void function() { int *ptr = NULL; ... }

Prefiero dejar las variables sin inicializar si no se usa el valor, ya que el compilador y Valgrind pueden darme mensajes de diagnóstico que me hagan saber que mi comprensión del código es incorrecta, si resulta que se utiliza la memoria no inicializada.


Nunca aplique el operador de direccionamiento indirecto a una variable de puntero no inicializada. Si no se inicializa, intentar usarlo invoca un comportamiento indefinido .
Los dos códigos anteriores invocan un comportamiento indefinido. En este caso, el resultado puede ser esperado o inesperado.

El último código funciona bien porque las variables globales se inicializan a 0 implícitamente. Por lo tanto, el puntero ptr se inicializa a NULL y obtiene el resultado correcto.


Tal vez puedas probar este código para saber lo que quieres saber:

#include <stdio.h> #include <stdlib.h> typedef struct _appl{ //the pointer int *ptr_int; float *ptr_float; double *ptr_double; char *ptr_char; //the basic data types int a_int; float a_float; double a_double; char a_char; struct _appl *next; } appl; //the pointers int *ptr_int_global; float *ptr_float_global; double *ptr_double_global; char *ptr_char_global; //the basic data types int a_int_global; float a_float_global; double a_double_global; char a_char_global; //pointer to structure data type appl *ptr_struct_global; //struct data type; appl a_struct_global; int main() { //the pointers int *ptr_int_local; float *ptr_float_local; double *ptr_double_local; char *ptr_char_local; //the basic data types int a_int_local; float a_float_local; double a_double_local; char a_char_local; //pointer to structure data type appl *ptr_struct_local; //struct data type; appl a_struct_local; //test the basic data types (local variables) puts("********"); puts("****first test : test the basic data types (local variables)"); puts("********"); printf("the value of a non-initialized int is : %d/n", a_int_local); printf("the value of a non-initialized float is : %f/n", a_float_local); printf("the value of a non-initialized double is : %f/n", a_double_local); printf("the value of a non-initialized char is : %d/n/n", a_char_local); //test the basic data types (global variables) puts("second test : test the basic data types (global variables)"); printf("the value of a non-initialized int is : %d/n", a_int_global); printf("the value of a non-initialized float is : %f/n", a_float_global); printf("the value of a non-initialized double is : %f/n", a_double_global); printf("the value of a non-initialized char is : %d/n/n", a_char_global); //test the pointers (local variables) puts("third test : test basic data type pointers (local variables)"); if(ptr_int_local == NULL) printf("a non-initialized int pointer is NULL/n"); else printf("a non-initialized int pointer is not NULL/n"); if(ptr_float_local == NULL) printf("a non-initialized float pointer is NULL/n"); else printf("a non-initialized float pointer is not NULL/n"); if(ptr_double_local == NULL) printf("a non-initialized double pointer is NULL/n"); else printf("a non-initialized double pointer is not NULL/n"); if(ptr_char_local == NULL) printf("a non-initialized char pointer is NULL/n/n"); else printf("a non-initialized char pointer is not NULL/n/n"); puts("attention ! sometimes a non-initialized char pointer (global variables) is NULL, while sometimes not !"); //test the pointers (global variables) puts("fourth test : test basic data type pointers (global variables)"); if(ptr_int_global == NULL) printf("a non-initialized int pointer is NULL/n"); else printf("a non-initialized int pointer is not NULL/n"); if(ptr_float_global == NULL) printf("a non-initialized float pointer is NULL/n"); else printf("a non-initialized float pointer is not NULL/n"); if(ptr_double_global == NULL) printf("a non-initialized double pointer is NULL/n"); else printf("a non-initialized double pointer is not NULL/n"); if(ptr_char_global == NULL) printf("a non-initialized char pointer is NULL/n/n"); else printf("a non-initialized char pointer is not NULL/n/n"); //test data structure (local variable) puts("fifth test : test data structure type (local variables)"); if(ptr_struct_local == NULL) printf("a non-initialized data structure pointer is NULL/n/n"); else printf("a non-initialized data structure pointer is not NULL/n/n"); //test data structure (global variable) puts("sixth test : test data structure type (global variables)"); if(ptr_struct_global == NULL) printf("a non-initialized data structure pointer is NULL/n/n"); else printf("a non-initialized data structure pointer is not NULL/n/n"); ptr_struct_local = (struct _appl*)malloc(sizeof(struct _appl*)); if(ptr_struct_local == NULL) printf("failed to allocate memory/n/n"); else printf("success of allocating memory/n/n"); appl *a = ptr_struct_local; //test the basic data types (in a local data structure variable) puts("/nseventh test : test the basic data types (in a local data structure variable)"); printf("the value of a non-initialized int is : %d/n", a->a_int); printf("the value of a non-initialized float is : %f/n", a->a_float); printf("the value of a non-initialized double is : %f/n", a->a_double); printf("the value of a non-initialized char is : %d/n/n", a->a_char); //test the pointers (in a local data structure variable) puts("eigth test : test the pointers (in a local data structure variable)"); if(a->ptr_int == NULL) printf("a non-initialized int pointer is NULL/n"); else printf("a non-initialized int pointer is not NULL/n"); if(a->ptr_float == NULL) printf("a non-initialized float pointer is NULL/n"); else printf("a non-initialized float pointer is not NULL/n"); if(a->ptr_double == NULL) printf("a non-initialized double pointer is NULL/n"); else printf("a non-initialized double pointer is not NULL/n"); if(a->ptr_char == NULL) printf("a non-initialized char pointer is NULL/n/n"); else printf("a non-initialized char pointer is not NULL/n/n"); ptr_struct_global = (struct _appl*)malloc(sizeof(struct _appl*)); if(ptr_struct_global == NULL) printf("failed to allocate memory/n/n"); else printf("success of allocating memory/n/n"); appl *b = ptr_struct_global; //test the basic data types (in a global data structure) puts("/nninth test : test the basic data types (in a global data structure)"); printf("the value of a non-initialized int is : %d/n", b->a_int); printf("the value of a non-initialized float is : %f/n", b->a_float); printf("the value of a non-initialized double is : %f/n", b->a_double); printf("the value of a non-initialized char is : %d/n/n", b->a_char); //test the pointers (in a global data structure) puts("tenth test : test the pointers (in a global data structure)"); if(b->ptr_int == NULL) printf("a non-initialized int pointer is NULL/n"); else printf("a non-initialized int pointer is not NULL/n"); if(b->ptr_float == NULL) printf("a non-initialized float pointer is NULL/n"); else printf("a non-initialized float pointer is not NULL/n"); if(b->ptr_double == NULL) printf("a non-initialized double pointer is NULL/n"); else printf("a non-initialized double pointer is not NULL/n"); if(b->ptr_char == NULL) printf("a non-initialized char pointer is NULL/n/n"); else printf("a non-initialized char pointer is not NULL/n/n"); }