Aquí está mi código:
#include <string.h>
#include <stdio.h>
typedef char BUF[8];
typedef struct
{
BUF b[23];
} S;
S s;
int main()
{
int n;
memcpy(&s, "1234567812345678", 17);
n = strlen((char *)&s.b) / sizeof(BUF);
printf("%d\n", n);
n = strlen((char *)&s) / sizeof(BUF);
printf("%d\n", n);
}
Usando gcc 8.3.0 u 8.2.1 con cualquier nivel de optimización, excepto -O0
, esto sale 0 2
cuando esperaba2 2
. El compilador decidió que strlen
está limitado b[0]
y, por lo tanto, nunca puede igualar o superar el valor dividido por
¿Es esto un error en mi código o un error en el compilador?
Esto no se explica claramente en el estándar, pero pensé que la interpretación principal de la procedencia del puntero era que para cualquier objeto X
, el código (char *)&X
debería generar un puntero que pueda iterar sobre el todo X
: este concepto debería mantenerse incluso si X
sucede que tiene sub-matrices como estructura interna.
(Pregunta adicional, ¿hay una bandera gcc para desactivar esta optimización específica?)
2 2
bajo varias opciones.s.b
se limita ab[0]
que se limita a 8 caracteres, y por lo tanto dos opciones: (1) fuera de límite de acceso en caso de que haya 8 caracteres que no son nulos, lo cual es UB, (2) hay un carácter nulo, en cuyo la len es menor que 8, por lo tanto, dividir por 8 da cero. EntoncesRespuestas:
Hay algunos problemas que puedo ver y pueden verse afectados por la forma en que el compilador decide diseñar la memoria.
En el código anterior
s.b
hay una matriz de 23 entradas de una matriz de 8 caracteres. Cuando hace referencia a solos.b
está obteniendo la dirección de la primera entrada en la matriz de 23 bytes (y el primer byte en la matriz de 8 caracteres). Cuando el código dice&s.b
, esto está pidiendo la dirección de la dirección de la matriz. Debajo de las cubiertas, es muy probable que el compilador genere algo de almacenamiento local, almacene la dirección de la matriz allí y proporcione la dirección del almacenamiento local astrlen
.Tienes 2 posibles soluciones. Son:
o
También traté de ejecutar su programa y demostrar el problema, pero tanto el sonido de claxon como la versión de gcc que tengo con las
-O
opciones siguieron funcionando como esperaba. Por lo que vale, estoy ejecutando clang versión 9.0.0-2 y gcc versión 9.2.1 en x86_64-pc-linux-gnu).fuente
Hay errores en el código.
por ejemplo, es arriesgado, aunque s comience por b debería ser:
El segundo strlen () también tiene errores
por ejemplo, debería ser:
La cadena sb, si se copia correctamente, debe tener 17 letras. No estoy seguro de cómo se almacenan las estructuras en la memoria, si están alineadas. ¿Has comprobado que sb realmente contiene los 17 caracteres copiados?
Entonces un strlen (sb) debería mostrar 17
El printf solo muestra números enteros, ya que% d es entero, y la variable n se declara como un número entero. sizeof (BUF), debe ser 8
Entonces un 17 dividido por 8 (17/8) debería imprimir 2 ya que n se declara como entero. Como memcpy se usó para copiar datos a sy no a sb, supongo que esto tiene que ver con las alineaciones de memoria; suponiendo que es una computadora de 64 bits, puede haber 8 caracteres en una dirección de memoria.
Por ejemplo, supongamos que alguien ha llamado un malloc (1), que el siguiente "espacio libre" no está alineado ...
La segunda llamada strlen muestra el número correcto, ya que la copia de cadena se realizó en la estructura s en lugar de en sb
fuente