2011-01-13 30 views
8

He estado tratando de crear un ciclo for que se repita basado en la longitud de un paquete de red. En la API existe una variable (size_t) por event.packet-> dataLength. Quiero iterar de 0 a event.packet-> dataLength-7 aumentando i por 10 cada vez que itera, pero estoy teniendo un mundo de problemas.Convirtiendo un size_t en un entero (C++)

Busqué soluciones pero no he podido encontrar nada útil. Traté de convertir el size_t a un int sin firmar y hacer la aritmética con eso, pero desafortunadamente no funcionó. Básicamente todo lo que quiero es esto:

for (int i = 0; i < event.packet->dataLength - 7; i+=10) { } 

Aunque cada vez que hago algo como esto o intento de mis conversiones del i < # parte es un número enorme. Dieron una declaración de printf en un tutorial para la API que usaba "% u" para imprimir el número real, sin embargo, cuando lo convierto en un int sin firmar, sigue siendo incorrecto. No estoy seguro de a dónde ir desde aquí. Cualquier ayuda sería muy apreciada :)

+3

Piensa en ello: ¿Cuál es el valor de 'static_cast (- 1)'? ¿Qué sucede cuando 'event.packet-> dataLength' es menor que 7? – genpfault

+0

¿Por qué no puedo 'i' ser un' size_t' también? Además, a menos que la longitud sea siempre igual a 7 mod 10, se trata de un bucle muy peculiar que se intentará. – OrangeDog

+0

¿Has intentado convertir 'event.packet-> dataLength' en' int'? – Dawson

Respuesta

4

¿Por qué no cambias el tipo de i?

for (size_t i = 0; i < event.packet->dataLength - 7; i+=10) { } 

intentar mantener todos los tipos de todas las variables utilizadas en conjunto del mismo tipo; los moldes deben ser evitados.

No hay un especificador de formato para size_t en C++ 03, tiene que convertir al tipo entero sin signo más grande que pueda e imprimir eso. (El especificador de formato para size_t en C++ 0x es %zu). Sin embargo, no se debe utilizar printf todos modos:

std::cout << i; // print i, even if it's a size_t 

Mientras que las corrientes pueden ser más detallado, que son más de tipo seguro y no requieren que memorizar nada.

Tenga en cuenta que su lógica real de bucle puede estar defectuosa. (¿Qué sucede, como notas genpfault, cuando dataLength - 7 es negativo?)

+0

Esto no ayudará si 'dataLength - 7' es negativo, y no creo que sirva de nada. –

+0

@David: No, no lo hará, es por eso que lo mencioné. Es difícil decir cuál es la solución sin conocer las intenciones. – GManNickG

+0

Intenté hacer que i size_t ya no funcionara. – JeanOTF

1

¿DataLength> = 7? Si el resultado de dataLength-7 es negativo, si lo interpreta como sin signo, el resultado es un entero muy grande.

0

Use size_t para i.

Para printf, si no tiene C99, solo C90, conviértalo en unsigned long o unsigned long long. Ej .:

for (size_t i = 0; i < 10; ++i) 
     //printf("%llu\n", (unsigned long long)i); 
     printf("%lu\n", (unsigned long)i); 

utilizan de alguna manera% zu

0

primer lugar, debe comprobar si event.packet->dataLength < 7. Ahora, si es menor a 7, obtienes valores menores a 0 usados ​​como sin firmar: p. 0 = 0x00000000; -1 = 0 - 1 = 0xFFFFFFFF.

Una vez más, el cheque:

if (event.packet->dataLength < 7) { 
    ... 
} else { 
    for (size_t i = 0; i < event.packet->dataLength - 7; i+=10) { } 
} 
2

hacer todo con la aritmética firmado. Proveedores:

for (int i = 0; i < int(event.packet->dataLength) - 7; i+=10) { } 

Una vez que empiece a usar la aritmética sin signo con valores que pueden ser negativas, y el uso de los operadores de comparación como <, estás en problemas. Mucho más fácil mantener las cosas firmadas.

+0

Hm, tuve que eliminar mi comentario original, pensando demasiado en términos de comportamiento garantizado. En la máquina complementaria de dos, con el compilador no perverso, es decir * en la práctica *, lo anterior funcionará. Pero esa conversión de un gran valor sin signo a 'int' es formalmente UB. Por lo tanto, mejor arregle el paréntesis. Cheers, –

+0

@Alf P. Steinbach: Gracias - incluso después de tu comentario me tomó un momento darme cuenta de lo que querías decir, así que no fue solo un error tipográfico. –

0

"cada vez que hago algo como esto o intento realizar mis conversiones, la parte i < # es un número enorme".

Eso indica que la longitud original del paquete es menor que 7 (resta 7).

Una solución es utilizar un tipo de entero con signo suficiente en la práctica, suficientemente grande, y la biblioteca estándar proporciona ptrdiff_t para tal fin. Al igual que,

#include <stdlib.h> // Not sure, but I think it was this one. 

typedef ptrdiff_t Size; 
typedef Size   Index; 

void foo() 
{ 
    // ... 
    for(Index i = 0; i < Size(event.packet->dataLength) - 7; i += 10) 
    { 
     // ... 
    } 
} 

Una solución más engorroso es la de insertar todo el asunto en una if que comprueba que el tamaño es al menos 7.

Saludos & HTH.,

0

Desde event.packet->dataLength devuelve un sin firmar tipo size_t:

1) Use size_t como el tipo de variable de índice.

2) Asegurarse de que las matemáticas no se desbordan. @beldaz. En lugar de restar 7 de event.packet->dataLength, agregue 7 a i.

// for (int i = 0; i < event.packet->dataLength - 7; i+=10) { } 
for (size_t i = 0; i + 7 < event.packet->dataLength; i += 10) { }