كيف تتخلص من تحذيرات "التحويل المهمل من ثابت السلسلة إلى تحذيرات"char*"" في دول مجلس التعاون الخليجي؟

StackOverflow https://stackoverflow.com/questions/59670

  •  09-06-2019
  •  | 
  •  

سؤال

لذا فأنا أعمل على قاعدة تعليمات برمجية كبيرة جدًا، وقمت مؤخرًا بالترقية إلى gcc 4.3، والذي يؤدي الآن إلى ظهور هذا التحذير:

تحذير:التحويل المهمل من ثابت السلسلة إلى "char*"

من الواضح أن الطريقة الصحيحة لإصلاح ذلك هي العثور على كل إعلان مثل

char *s = "constant string";

أو استدعاء وظيفة مثل:

void foo(char *s);
foo("constant string");

وصنعها const char مؤشرات.ومع ذلك، فإن هذا يعني لمس 564 ملفًا، كحد أدنى، وهي ليست مهمة أرغب في تنفيذها في هذا الوقت.المشكلة الآن هي أنني أركض مع -werror, ، لذا أحتاج إلى طريقة ما لقمع هذه التحذيرات.كيف أقوم بذلك؟

هل كانت مفيدة؟

المحلول

أعتقد مرور -Wno-write-strings إلى دول مجلس التعاون الخليجي سوف يمنع هذا التحذير.

نصائح أخرى

أي وظائف تقوم بتمرير سلسلة حرفية إليها "I am a string literal" يجب استخدام char const * كنوع بدلا من char*.

إذا كنت تريد إصلاح شيء ما، فأصلحه بشكل صحيح.

توضيح:

لا يمكنك استخدام سلسلة حرفية لتهيئة السلاسل التي سيتم تعديلها، لأنها من النوع const char*.التخلص من الثبات لتعديلها لاحقًا هو سلوك غير محدد, ، لذلك عليك نسخ ملفك const char* سلاسل char بواسطة char إلى المخصصة ديناميكيا char* السلاسل من أجل تعديلها.

مثال:

#include <iostream>

void print(char* ch);

void print(const char* ch) {
    std::cout<<ch;
}

int main() {
    print("Hello");
    return 0;
}

تحقق من دول مجلس التعاون الخليجي البراغما التشخيصية الدعم، وقائمة -W خيارات التحذير (تغير: رابط جديد لخيارات التحذير).

بالنسبة لدول مجلس التعاون الخليجي، يمكنك استخدام #pragma warning التوجيهات مثل وأوضح هنا.

كان لدي مشكلة مماثلة، وحلها مثل هذا:

#include <string.h>

extern void foo(char* m);

int main() {
    // warning: deprecated conversion from string constant to ‘char*’
    //foo("Hello");

    // no more warning
    char msg[] = "Hello";
    foo(msg);
}

هل هذه طريقة مناسبة لحل هذا؟ليس لدي إمكانية الوصول إليها foo لتكييفه لقبوله const char*, ، على الرغم من أن هذا سيكون حلاً أفضل (لأن foo لم يتغير m).

إذا كانت قاعدة تعليمات برمجية نشطة، فقد لا تزال ترغب في ترقية قاعدة التعليمات البرمجية.بالطبع، إجراء التغييرات يدويًا ليس ممكنًا ولكن أعتقد أنه يمكن حل هذه المشكلة مرة واحدة وإلى الأبد بأداة واحدة sed يأمر.ومع ذلك، لم أجربه، لذا خذ ما يلي بحذر.

find . -exec sed -E -i .backup -n \
    -e 's/char\s*\*\s*(\w+)\s*= "/char const* \1 = "/g' {} \;

قد لا يؤدي هذا إلى العثور على جميع الأماكن (حتى مع عدم مراعاة استدعاءات الوظائف) ولكنه قد يخفف المشكلة ويجعل من الممكن إجراء التغييرات القليلة المتبقية يدويًا.

لا يمكنني استخدام مفتاح التحويل البرمجي.لذلك حولت هذا:

char *setf = tigetstr("setf");

الى هذا:

char *setf = tigetstr((char *)"setf");

إليك كيفية القيام بذلك بشكل مضمن في ملف، لذلك لا يتعين عليك تعديل ملف Makefile الخاص بك.

// gets rid of annoying "deprecated conversion from string constant blah blah" warning
#pragma GCC diagnostic ignored "-Wwrite-strings"

ويمكنك بعد ذلك...

#pragma GCC diagnostic pop

يستبدل

char *str = "hello";

مع

char *str = (char*)"hello";

أو إذا كنت تتصل بالوظيفة:

foo("hello");

استبدل هذا بـ

foo((char*) "hello");

بدلاً من:

void foo(char *s);
foo("constant string");

هذا يعمل:

void foo(const char s[]);
foo("constant string");

في لغة C++، استخدم const_cast كما هو موضح أدناه

char* str = const_cast<char*>("Test string");

Test string هي سلسلة ثابتة.لذلك يمكنك حل مثل هذا:

char str[] = "Test string";

أو:

const char* str = "Test string";
printf(str);

لماذا لا تستخدم فقط نوع الصب؟

(char*) "test"

قم بالطباعة من سلسلة ثابتة إلى مؤشر char، على سبيل المثال.

char *s = (char *) "constant string";

في C++، استبدل:

char *str = "hello";

مع:

std::string str ("hello");

وإذا أردت مقارنتها:

str.compare("HALLO");

لا أفهم كيفية تطبيق الحل الخاص بك :( – kalmanIsAGameChanger

من خلال العمل مع Arduino Sketch، كانت لدي وظيفة تتسبب في تحذيراتي.

الوظيفة الأصلية:شار StrContains (شار * شارع، شار * sfind)

لإيقاف التحذيرات أضفت مقدار ثابت أمام char *str و char *sfind.

معدل:char StrContains(const char *str, const char *sfind).

ذهبت جميع التحذيرات بعيدا.

انظر هذا الوضع:

typedef struct tagPyTypeObject
{
    PyObject_HEAD;
    char *name;
    PrintFun print;
    AddFun add;
    HashFun hash;
} PyTypeObject;

PyTypeObject PyDict_Type=
{
    PyObject_HEAD_INIT(&PyType_Type),
    "dict",
    dict_print,
    0,
    0
};

شاهد حقل الاسم، في دول مجلس التعاون الخليجي يتم تجميعه دون سابق إنذار، ولكن في g++ سيتم تجميعه، لا أعرف السبب.

يمكنك أيضًا إنشاء سلسلة قابلة للكتابة من سلسلة ثابتة عن طريق الاتصال strdup().

على سبيل المثال، هذا الرمز يولد تحذيرا:

putenv("DEBUG=1");

ومع ذلك، فإن التعليمة البرمجية التالية لا تفعل ذلك (فهي تقوم بعمل نسخة من السلسلة الموجودة على الكومة قبل تمريرها إلى putenv):

putenv(strdup("DEBUG=1"));

في هذه الحالة (وربما في معظم الحالات الأخرى) يعد إيقاف التحذير فكرة سيئة - فهو موجود لسبب ما.قد يكون البديل الآخر (جعل جميع السلاسل قابلة للكتابة افتراضيًا) غير فعال.

استمع لما يقوله لك المترجم!

فقط استخدم الخيار -w لـ g++

مثال:

g++ -w -o simple.o simple.cpp -lpthread

تذكر أن هذا لا يتجنب الإهمال بل يمنع عرض رسالة تحذير على الجهاز.

الآن، إذا كنت تريد حقًا تجنب الإهمال، فاستخدم الكلمة الأساسية const مثل هذا:

const char* s="constant string";  

لماذا لا تستخدم -Wno-deprecated خيار تجاهل رسائل التحذير المهملة؟

المشكلة الآن هي أنني أعمل مع -Werror

هذه هي مشكلتك الحقيقية، المنظمة البحرية الدولية.يمكنك تجربة بعض الطرق الآلية للانتقال من (char *) إلى (const char *) ولكني أود أن أضع أموالاً عليها وليس فقط العمل.سيتعين عليك إشراك إنسان في بعض الأعمال على الأقل.على المدى القصير، ما عليك سوى تجاهل التحذير (ولكن اتركه في IMO، وإلا فلن يتم إصلاحه أبدًا) وقم فقط بإزالة -Werror.

اشكركم جميعا على المساعدة.الانتقاء من هنا وهناك يأتي هذا الحل.هذا يجمع نظيفة.لم تختبر الكود بعد.غداً...ربما...

const char * timeServer[] = { "pool.ntp.org" }; // 0 - Worldwide 
#define WHICH_NTP            0 // Which NTP server name to use.
...
sendNTPpacket(const_cast<char*>(timeServer[WHICH_NTP])); // send an NTP packet to a server
...
void sendNTPpacket(char* address) { code }

أعلم أن هناك عنصرًا واحدًا فقط في مصفوفة timeServer.ولكن يمكن أن يكون هناك المزيد.تم التعليق على الباقي في الوقت الحالي لحفظ الذاكرة.

إجابة BlackShift مفيدة جدًا، وقد استخدمتها على النحو التالي:

extern string execute(char* cmd) {
            FILE* pipe = popen(cmd, "r");
            if (!pipe) return "ERROR";
            char buffer[256];
            std::string result = " ";
            while(!feof(pipe)) {
                    if(fgets(buffer, 128, pipe) != NULL)
                            result += buffer;
            }
            pclose(pipe);
            return result;
    }
    int main(){
            char cmd[]="grep -A1 'xml' out1.txt  | grep read|awk -F'=' 'BEGIN{sum=0}{sum=sum+$NF}END{print sum}'";
            string result=execute(cmd);
            int numOfBytes= atoi(result.c_str());   
            cout<<"Number of bytes = "<<numOfBytes<<endl;
            return 0;
    }
PyTypeObject PyDict_Type=
{ ...

PyTypeObject PyDict_Type=
{
  PyObject_HEAD_INIT(&PyType_Type),
                     "dict",
                     dict_print,
                     0,
                     0
}; 

شاهد حقل الاسم، في دول مجلس التعاون الخليجي يتم تجميعه دون سابق إنذار، ولكن في g++ سيتم تجميعه، لا أعرف السبب.

في gcc (Compiling C), ، -Wno-write-strings نشط بشكل افتراضي.

في g++ (Compiling C++) -Write-strings نشط بشكل افتراضي

هذا هو السبب في وجود سلوك مختلف.بالنسبة لنا باستخدام وحدات الماكرو من Boost_python يولد مثل هذه التحذيرات.لذلك نستخدم -Wno-write-strings عند تجميع C++ لأننا نستخدمه دائمًا -Werror

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top