предупреждения преобразования типов при переносе 32-битного приложения в 64-битное приложение с помощью оператора sizeof - PullRequest
2 голосов
/ 06 июля 2011

Я портирую приложение с 32 бит на 64 бит.Приложение включает в себя сгенерированный gSoap исходный код ANSI C.Прототипы нескольких функций мыла включают int типы данных в списке аргументов, такие как:

int PASCAL FAR setsockopt (
                       __in SOCKET s,
                       __in int level,
                       __in int optname,
                       __in_bcount_opt(optlen) const char FAR * optval,
                       __in int optlen);

Но при вызове в stdsoap2.c 5-йаргумент в этом примере передается оператору sizeof:

if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
{ ...
}

Оператор sizeof возвращает значение типа size_t , которое является просто без знака int .При компиляции в 32-битной среде это не представляет никаких проблем, однако при компиляции в 64-битной среде предупреждение: «Преобразование из« unsigned __int64 »в« int »может привести к потере данных» .

Я понимаю проблему потери данных, мой вопрос , где и как было бы лучше всего в коде решить проблему, исключая приведение типа (int) при каждом появленииоператор sizeof передается как int в stdsoap2.c (только в stdsoap.c есть 32 предупреждения).Я хотел бы избежать редактирования автоматически сгенерированного исходного файла, если это возможно.

Для тех, кто знаком с методами gsoap, я включил следующее:

#ifdef WITH_SOAPDEFS_H
# include "soapdefs.h"      /* include user-defined stuff */
#endif

и использую soapdefs.h в своем проекте.Этот файл имеет широкий охват проекта, возможно, этот файл будет хорошим , где для решения проблемы, тогда вопрос будет просто how ?

Спасибо, Ryyker

Ответы [ 2 ]

4 голосов
/ 06 июля 2011

size_t не "просто unsigned int";как показывает предупреждение, на 64-битной платформе он обычно больше этого.

Где вы должны выполнить проверку, зависит от приложения, но если вы передаете значение выражения sizeof, выможет заменить это соответствующим образом определенной константой:

enum {
    SIZEOF_LINGER = sizeof(struct linger);
};

Компилятор выдаст предупреждение, если константа слишком велика для преобразования, поэтому, если вы скомпилируете (эквивалент GCC) -Wall -Werror, выВы в безопасности.

1 голос
/ 06 июля 2011

в тех случаях, когда я не могу изменить метод, взяв вместо него int вместо size_t, я обычно решаю повысить boost :: numeric_cast в C ++ или аналогичный в C, это, кажется, лучше всего сделать и эффективно избавиться от предупреждения, пока все еще остается в безопасности.

Основная идея:

int safe_cast( size_t n )
{
  if( n > INT_MAX )
  {
     //do something to handle this error
  }
  return (int) n;
}

В вашем случае, однако, вы можете быть уверены, что sizeof( struct linger ) не будет превышать INT_MAX, поэтому вы могли бы также предоставить глобальную константу, которая является целым и содержит этот размер.

...