কনস্টেরার * অ্যারে আরম্ভের কমাটি অনুপস্থিত থাকলে সংকলক সতর্কতা তৈরি করুন


53

আমি আমার সি কোডে স্ট্রিং আক্ষরিক টেবিলগুলি ব্যবহার করছি। এই টেবিলগুলি কম বেশি কম দেখায়:

static const char* const stateNames[STATE_AMOUNT] =
{
    "Init state",
    "Run state",
    "Pause state",
    "Error state",
};

উপরের কোডটিতে সমস্যাটি হ'ল যদি টেবিলটি দীর্ঘ হয় এবং বিকাশের সময় পরিবর্তিত হয় তবে আমি সময়ে সময়ে একটি কমা ভুলে যাই। অনুপস্থিত কমা নিয়ে সমস্যা ছাড়াই কোডটি সংকলন করে, তবে আমার প্রোগ্রামটি শেষ স্ট্রিংটি সেট হয়ে যাওয়ার সাথে সাথে ক্র্যাশ হয়ে যায় NULL। আমি যাচাই করতে MinGW এবং কাইল সংকলক ব্যবহার করেছি।

কমা অনুপস্থিত থাকলে আমার আরম্ভের জন্য কোনও সংকলক সতর্কতা উত্পন্ন করার কোনও উপায় আছে কি?


1
যখন আপনি কেবল এই টেবিলটিতে কোনও রাজ্য যুক্ত করতে ভুলে যান তবে কি হবে?
জেরোইন 3

1
@ জেরোয়ান 3 সত্য এটি একই ত্রুটির কারণ হতে পারে। স্ট্যাটিক জোর ব্যবহারের সাথে তালিকার দৈর্ঘ্যের পরীক্ষার জন্য STATE_AMOUNT এছাড়াও এই সমস্যার সমাধান করে।
জনি শুবার্ট

উত্তর:


62

প্রতিটি const char*বন্ধনীর জুড়ে প্রতিটি মুছে ফেলা হলে নিম্নলিখিত স্নিপেটে প্রদর্শিত সমস্যাটি সমাধান করা উচিত:

static const char* const stateNames[5] =
{
    ("Init state"),
    ("Run state"),
    ("Pause state")     //comma missing
    ("Pause state3"),
    ("Error state")
};

আপনি যদি কমাটি ভুলে যান তবে আপনি এর মতো একটি সংকলন ত্রুটি পাবেন: error: called object is not a function or function pointer

সরাসরি নমুনা


মনে রাখবেন যে আপনি কমাটি ভুলে গেলে যা ঘটেছিল তা হ'ল সি আসলে পরবর্তী দুটি কমা বা অ্যারের সমাপ্তি পর্যন্ত দুটি (বা আরও) স্ট্রিংটি সংহত করবে। উদাহরণস্বরূপ বলা যাক যে আপনি কমাটি ভুলে গেছেন নীচের মত:

static const char* const stateNames[] =
{
    "Init state",
    "Run state",
    "Pause state" //comma missing
    "Pause state3" //comma missing
    "Error state"
};

int main(void)
{  
    printf("%s\n", stateNames[0]);
    return 0;    
}

এটি যা gcc-9.2উত্পন্ন করে (অন্যান্য সংকলকগুলি একই কোড উত্পন্ন করে):

.LC0:
        .string "Init state"
        .string "Run state"
        .string "Pause statePause state3Error state" ; oooops look what happened
        .quad   .LC0
        .quad   .LC1
        .quad   .LC2
main:
        push    rbp
        mov     rbp, rsp
        mov     eax, OFFSET FLAT:.LC0
        mov     rdi, rax
        call    puts
        mov     eax, 0
        pop     rbp
        ret

এটি স্পষ্ট যে শেষ তিনটি স্ট্রিং সংমিশ্রিত এবং অ্যারে আপনি যে দৈর্ঘ্যের প্রত্যাশা করবেন তা নয়।


33

আপনি সংকলকটিকে অ্যারে গণনা করতে এবং অপ্রত্যাশিত ফলাফল হলে ত্রুটি বার্তা উত্পন্ন করতে দিতে পারে:

enum { STATE_AMOUNT = 4 };

static const char* const stateNames[] =
{
    "Init state",
    "Run state",
    "Pause state"    // <--- missing comma
    "Error state",
};

_Static_assert( sizeof stateNames / sizeof *stateNames == STATE_AMOUNT,
        "oops, missed a comma" );

ধারণাগুলি বাস্তবায়নের জন্য এই থ্রেডটি দেখুন_Static_assert যদি আপনার সংকলকটি খুব পুরানো এবং সমর্থন না করে।

বোনাস হিসাবে, আপনি যখন নতুন রাজ্য যুক্ত করবেন তবে স্ট্রিং টেবিলটি আপডেট করতে ভুলে যাবেন এটির সাথেও এটি সহায়তা করতে পারে। তবে আপনি এক্স ম্যাক্রোগুলিও দেখতে চাইতে পারেন।


অভিশাপ .... এই ঠিক উত্তরটি আমি টাইপ করতে যাচ্ছিলাম!
ওয়েল্ডার

11

এটিকে সমাধান করার জন্য আমি সবসময় সুস্পষ্ট আকারের অ্যারের একটি রেফারেন্স ব্যবহার করেছি।

// no explicit size here
static const char* const stateNames[] =
{
    "Init state",
    "Run state",
    "Pause state",
    "Error state",
};
static const char* const (&stateNameVerifier)[STATE_AMOUNT] = stateNames;

http://coliru.stacked-crooked.com/a/593fc2eac80782a6

main.cpp:10:32: error: reference to type 'const char *const [5]' could not bind to an lvalue of type 'const char *const [4]'
static const char* const (&stateNameVerifier)[STATE_AMOUNT] = stateNames;

4
একটি স্থিতিশীল দৃ .় বক্তব্য অনেক বেশি মার্জিত সমাধান বলে মনে হয়। আমি মনে করি ভাষার অংশ হিসাবে স্থিতিশীল দাবিগুলি প্রয়োগ করার আগে আপনি এটি করার অভ্যাস পেয়েছেন? অ্যারেটির প্রত্যাশিত আকার যাচাই করে এমন স্ট্যাটিক প্রতিবেদনের মাধ্যমে আপনি কি এখনও এর কোনও সুবিধা দেখতে পাচ্ছেন?
কোডি গ্রে

2
@ কোডি গ্রে: হ্যাঁ, আপনি এখন উল্লেখ করেছেন যে এটি প্রাক-স্থির-
দৃsert় ছিল

9

এটি আপনাকে সাহায্যের জন্য সংকলকটি নিয়ে আসে না, তবে আমি নীচের মতো এটি লিখতে দেখি মানুষের পক্ষে কমা ছাড়ানো সহজ হয়:

static const char* const stateNames[STATE_AMOUNT] =
{
      "Init state"
    , "Run state"
    , "Pause state"
    , "Error state"
};

3
শেষে কিছু যুক্ত করা খুব সহজ। কমা যোগ করতে আপনাকে পূর্ববর্তী লাইনটি সম্পাদনা করতে হবে না। (কমা নিখোঁজ হওয়ার মূল কারণ।)
ডেটাফিডলার

@ ডেটাফিডলার: একমত কোনও এসকিউএল নির্বাচন কমান্ডের কলামগুলির তালিকাটি সূক্ষ্মভাবে সুরক্ষিত করার জন্য এটি দরকারী, যখন আপনি কমেন্ট করছেন এবং সেগুলিতে আন-মন্তব্য করছেন। আপনি প্রায়শই সর্বশেষটি পরিবর্তন করতে চান; আপনি খুব কমই প্রথম পরিবর্তন করতে চান। এই আইটেমটি মন্তব্য করার জন্য আপনাকে একাধিক লাইন সংশোধন করতে হবে না।
জোনাথনজ ২৪
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.