Как получить результат strlen в int без предупреждения при компиляции с / Wp64

int l = strlen (s);

предупреждение C4244: '=': преобразование из '__w64 int' в 'int', возможная потеря данных

Мне нужно заменить strlen встроенной функцией int l = new_strlen (s);

Но как мне переносимо получить результат strlen в int без предупреждения и без использования прагм? Я могу гарантировать, что в моей строке не более 2 миллиардов символов!

Все очевидные вещи, такие как reinterpret_cast, static_cast, также вызывают ошибки или предупреждения.

Обновлено: Аргх. приведение в стиле c: (int) действительно работает. Я был убежден, что это не так.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
0
12 235
7

Ответы 7

Бросьте это:

int i = (int) strlen(s);

В этом случае ничего. Это просто создаст временный int и инициализирует его значением, возвращаемым из strlen (). В других случаях приведение типов в стиле C может быть опасным, если есть более безопасные альтернативы, такие как static_cast или dynamic_cast.

John Dibling 15.10.2008 01:33

Или не используйте подписанный int. Возвращаемое значение strlen () беззнаковое.

const char * str = "Hello";
int len = static_cast< int >( strlen( str ) );
return len;

Этот код не выдает никаких ошибок или предупреждений даже на уровне предупреждения 4 (VS2005). Какой компилятор вы используете?

I need to replace strlen with an inline function int l = new_strlen(s);

Обратите внимание, что в VC++ strlen автоматически заменяется встроенной версией при создании оптимизированной версии.

Также обратите внимание, что / Wp64 устарел в VS2008; видимо это ненадежный.

/ Wp64, вероятно, является пустой тратой времени для 32-битных сборок, но он действительно полезен для 64-битных сборок, поскольку позволяет выводить предупреждения, которые вы не получили бы в противном случае.

bk1e 14.10.2008 19:07

Если вы строите для x64, вы все равно получите предупреждения. / Wp64 предназначен для 32-разрядной сборки, но вы хотите, чтобы вас предупредили о потенциальных проблемах с 64-разрядной версией. Но, тем не менее, он сломан: blogs.msdn.com/vcblog/archive/2007/08/10/…

Roger Lipscombe 14.10.2008 20:04

Я понимаю, что / Wp64 был разработан, чтобы выдавать предупреждения о совместимости с 64-разрядной версией в 32-разрядных сборках. Однако, если я открою командную строку кросс-инструментов Visual C++ x64 и запускаю cl.exe с / Wp64 и без него, я получаю предупреждения о неверном указателе <=> целочисленных приведениях только тогда, когда я указываю / Wp64 или / Wall, а не / W4.

bk1e 15.10.2008 08:50

В случаях, когда у вас действительно есть веская причина для усечения указателей, вы можете заставить /Wp64 принять ваш код, сложив несколько приведений. Эти случаи редки. Один пример: драйверы устройств для устаревших устройств PCI, выполняющих DMA, с выделенной памятью ниже предела 4 ГБ. (Примечание: есть также макрос PtrToUlong(), который прояснит ваши намерения.)

Это одиночное приведение выдаст предупреждение:

const char* p = "abc";
unsigned int u = reinterpret_cast<unsigned int>(p);

wp64.cpp (10): предупреждение C4311: 'reinterpret_cast': усечение указателя с 'const char *' до 'unsigned int'

Но эти составные броски не будут:

const char* p = "abc";
unsigned int u = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(p));

Я не могу воспроизвести ваше предупреждение с версией компилятора, который я установил, но подозреваю, что ваша проблема связана с тем, что вы преобразуете 64-битный беззнаковый size_t в 32-битный подписанный int.

Возможно, вам повезет больше, если вы сложите несколько приведений для преобразования 64-битного в 32-битное и преобразования без знака в знак:

const char* s = "abcdef";
int l = static_cast<int>(static_cast<intptr_t>(strlen(s)));

Кроме того, если вы собираете двоичные файлы как x86, так и x64, вы можете отключить /Wp64 для своих 32-разрядных сборок, чтобы вам не приходилось аннотировать какие-либо типы с помощью __w64. Использование /Wp64 для ваших 64-битных сборок приведет к обнаружению множества ошибок.

если вы понимаете предупреждение, вполне допустимо отключить предупреждение вместо того, чтобы складывать приведение или какой-либо другой запутанный беспорядок в качестве обходного пути.

A pragma warning directive with the suppress specifier suppresses the warning only for the line of code that immediately follows the #pragma warning statement.

#pragma warning( suppress : 6001 ) 
arr[i+1] = 0; // Warning 6001 is suppressed
j++; // Warning 6001 is reported

(msvc specific)

Другие вопросы по теме