একই ঠিকানাটির যুক্তিযুক্ত বিন্দুতে পয়েন্টার এবং বিন্দুতে ফাংশন কল


14

আমি এমন একটি ফাংশন লিখতে চাই যা ডেটার একটি অ্যারে ইনপুট করে এবং পয়েন্টার ব্যবহার করে ডেটার অ্যারের আউটপুট দেয়।

আমি ভাবছি উভয় srcএবং dstএকই ঠিকানার দিকে ইঙ্গিত করলে ফলাফল কী হবে কারণ আমি জানি যে সংকলক কনস্টের জন্য অনুকূল করতে পারে। এটা কি অপরিবর্তিত আচরণ? (আমি সি এবং সি ++ উভয়কেই ট্যাগ করেছি কারণ আমি নিশ্চিত নই যে উত্তরগুলির মধ্যে তাদের মধ্যে পার্থক্য থাকতে পারে কিনা এবং আমি উভয় সম্পর্কেই জানতে চাই))

void f(const char *src, char *dst) {
    dst[2] = src[0];
    dst[1] = src[1];
    dst[0] = src[2];
}

int main() {
    char s[] = "123";
    f(s,s);
    printf("%s\n", s);
    return 0;
}

উপরোক্ত প্রশ্নের পাশাপাশি, আমি যদি constমূল কোডটিতেই মুছে ফেলি তবে এটি কি ভাল-সংজ্ঞায়িত ?

উত্তর:


17

যদিও এটি সত্য যে আচরণটি সুস্পষ্টভাবে সংজ্ঞায়িত হয়েছে - এটি ঠিক নয় যে কম্পাইলাররা আপনার বোঝার অর্থটি "কনস্টের জন্য অনুকূলিত করতে" পারেন।

অর্থাত, একটি সংকলককে ধরে নিতে দেওয়া হয় না যে কেবলমাত্র প্যারামিটারটি হ'ল const T* ptr, দ্বারা চিহ্নিত মেমরিটি ptrঅন্য পয়েন্টারের মাধ্যমে পরিবর্তন করা হবে না। পয়েন্টারগুলিও সমান হতে হবে না। constআপনার দ্বারা একটি বাধ্যবাধকতা (ফাংশন =) যে পয়েন্টার মাধ্যমে পরিবর্তন করতে না - একটি বাধ্যবাধকতা, না একটি গ্যারান্টি।

আসলে সেই গ্যারান্টিটি পেতে, আপনাকে restrictকীওয়ার্ড দিয়ে পয়েন্টারটি চিহ্নিত করতে হবে । এইভাবে, আপনি যদি এই দুটি ফাংশন সংকলন করেন:

int foo(const int* x, int* y) {
    int result = *x;
    (*y)++;
    return result + *x;
}

int bar(const int* x, int* restrict y) {
    int result = *x;
    (*y)++;
    return result + *x;
}

foo()ফাংশন থেকে দুইবার পড়তে হবে x, যখন bar()শুধুমাত্র একবার এটা পড়তে হবে:

foo:
        mov     eax, DWORD PTR [rdi]
        add     DWORD PTR [rsi], 1
        add     eax, DWORD PTR [rdi]  # second read
        ret
bar:
        mov     eax, DWORD PTR [rdi]
        add     DWORD PTR [rsi], 1
        add     eax, eax              # no second read
        ret

এটি সরাসরি দেখুন GodBolt

restrictসি তে কেবল একটি কীওয়ার্ড (সি 99 থেকে); দুর্ভাগ্যক্রমে, এটি এখন পর্যন্ত সি ++ তে প্রবর্তিত হয়নি (খারাপ কারণে যে এটি সি ++ তে প্রবর্তন করা আরও জটিল)। অনেক সংকলক এটি কিন্ডা-সমর্থন করেন, তবে, হিসাবে __restrict

নীচের লাইন: সংকলকটি সংকলনের সময় অবশ্যই আপনার "রহস্যজনক" ব্যবহারের ক্ষেত্রে সমর্থন f()করবে এবং এতে কোনও সমস্যা হবে না।


জন্য ব্যবহারের ক্ষেত্রে সম্পর্কিত এই পোস্টটি দেখুন restrict


const"আপনার দ্বারা কোনও বাধ্যবাধকতা নয় (= ফাংশন) সেই পয়েন্টারের মাধ্যমে পরিবর্তন না করা"। সি স্ট্যান্ডার্ড ফাংশনটিকে constএকটি কাস্টের মাধ্যমে সরিয়ে ফেলার অনুমতি দেয় এবং তারপরে ফলাফলের মাধ্যমে অবজেক্টটি সংশোধন করে। মূলত, constঅজান্তে কোনও বস্তুর সংশোধন এড়াতে সহায়তা করার জন্য প্রোগ্রামারের কাছে কেবল পরামর্শদাতা এবং একটি সুবিধা।
এরিক পোস্টপিসিল

@ এরিকপোস্টপিসিল: এটি একটি বাধ্যবাধকতা যা থেকে আপনি বেরিয়ে আসতে পারেন।
einpoklum

যে বাধ্যবাধকতা থেকে আপনি বেরিয়ে আসতে পারেন তা বাধ্যবাধকতা নয়।
এরিক পোস্টপিসিল

2
@ এরিকপোস্টপিসিল: ১. আপনি এখানে চুল ভাগ করছেন। 2. এটি সত্য নয়।
einpoklum

1
এই কারণেই memcpyএবং আর্গুমেন্টের strcpyসাথে ঘোষিত হয় restrict, যদিও memmoveএটি হয় না - কেবল পরেরটি মেমরি ব্লকগুলির মধ্যে ওভারল্যাপের অনুমতি দেয়।
বারমার

5

এটি constকোয়ালিফায়ার সহ এবং তার ছাড়াই ভালভাবে সংজ্ঞায়িত (সি ++ এ, সি-তে আর নিশ্চিত নয়) ।

সন্ধানের জন্য প্রথম জিনিসটি হ'ল কঠোর আলিয়াজিং নিয়ম 1 । যদি srcএবং dstএকই বস্তুর দিকে নির্দেশ করে:

সংক্রান্ত constকোয়ালিফায়ার, আপনি হয়তো বলবেন কবে থেকে dst == srcআপনার ফাংশন কার্যকরভাবে মডিফাই কি srcপয়েন্ট, srcযেমন যোগ্যতাসম্পন্ন করা উচিত হবে না const। এটি কিভাবে constকাজ করে না । দুটি ক্ষেত্রে বিবেচনা করা দরকার:

  1. যখন কোনও বস্তুকে সংজ্ঞায়িত করা constহয় char const data[42];, যেমন এটি হয় , তখন এটি সংশোধন করে (প্রত্যক্ষ বা পরোক্ষভাবে) অনির্ধারিত আচরণের দিকে নিয়ে যায়।
  2. যখন কোনও constবস্তুর রেফারেন্স বা পয়েন্টারটি সংজ্ঞায়িত করা হয়, যেমন হিসাবে char const* pdata = data;, কেউ অন্তর্নিহিত অবজেক্টটি সংশোধন করতে পারে তবে শর্ত থাকে যে এটি const2 হিসাবে সংজ্ঞায়িত করা হয়নি (দেখুন 1.।) সুতরাং নিম্নলিখিতটি ভালভাবে সংজ্ঞায়িত করা হয়েছে:
int main()
{
    int result = 42;
    int const* presult = &result;
    *const_cast<int*>(presult) = 0;
    return *presult; // 0
}

1) কড়া আলিয়াজিংয়ের নিয়ম কী?
2) Is const_castনিরাপদ?


হয়তো ওপি মানে অ্যাসাইনমেন্টগুলির সম্ভাব্য পুনঃনির্মাণ?
ইগোর আর।

char*এবং char const*উপযুক্ত নয়। _Generic((char *) 0, const char *: 1, default: 0))শূন্য মূল্যায়ন।
এরিক পোস্টপিসিল

"যখন কোনও constউপাদানের রেফারেন্স বা পয়েন্টার সংজ্ঞায়িত করা হয়" বাক্যটি ভুল হয়। আপনার অর্থ constহ'ল যখন কোনও যোগ্যতার প্রকারের জন্য কোনও রেফারেন্স বা পয়েন্টার সংজ্ঞায়িত করা হয়, তার অর্থ এই নয় যে এটি নির্দিষ্ট করা বস্তুটি পরিবর্তিত হতে পারে না (বিভিন্ন উপায়ে)। (যদি পয়েন্টারটি কোনও constবস্তুকে নির্দেশ করে , তার অর্থ বস্তুটি প্রকৃতপক্ষে constসংজ্ঞা দ্বারা হয়, সুতরাং এটির সংশোধন করার চেষ্টা করার আচরণটি সংজ্ঞায়িত হয় না))
এরিক পোস্টপিসিল

@ এরিক, আমি কেবল তখনই নির্দিষ্ট যখন প্রশ্নটি স্ট্যান্ডার্ড বা ট্যাগ হওয়া সম্পর্কিত language-lawyer। যথার্থতা হ'ল একটি মূল্য যা আমি লালন করি তবে আমি আরও সচেতন এটি আরও জটিলতার সাথে আসে। এখানে আমি সিদ্ধান্ত নিয়েছি সরলতা এবং সহজে বোঝার বাক্যগুলিতে যাব, কারণ আমি ওপি চেয়েছিলাম এটিই বারণ। আপনি যদি অন্যথায় মনে করেন তবে দয়া করে উত্তর দিন, আমি এটিকে প্রথম স্থান দেওয়ার মধ্যে প্রথমে থাকব। যাইহোক, আপনার মন্তব্যের জন্য আপনাকে ধন্যবাদ।
ওয়াইএসসি

3

এটি সি-তে সুস্পষ্টভাবে সংজ্ঞায়িত করা হয়েছে কড়াকড় আলিয়াজিং নিয়ম charপ্রকারের সাথে প্রযোজ্য নয় বা একই ধরণের দুটি পয়েন্টার সহ প্রযোজ্য নয় ।

আপনি "অপ্টিমাইজ করা const" বলতে যা বোঝায় তা নিশ্চিত নই । আমার সংকলক (জিসিসি 8.3.0 x86-64) উভয় ক্ষেত্রেই একই কোড তৈরি করে same আপনি যদি restrictপয়েন্টারে সুনির্দিষ্ট যোগ করে থাকেন তবে উত্পন্ন কোডটি কিছুটা ভাল, তবে এটি আপনার ক্ষেত্রে কার্যকর হবে না, পয়েন্টারগুলি একই হবে।

(সি 11 §6.5 7)

একটি অবজেক্টের কেবলমাত্র একটি নিম্নমানের এক্সপ্রেশন দ্বারা তার সঞ্চিত মান অ্যাক্সেস করতে হবে যা নিম্নলিখিত ধরণের
একটি হতে পারে : - বস্তুর কার্যকর ধরণের সাথে সামঞ্জস্যপূর্ণ একটি প্রকার,
- কোনও ধরণের কার্যকর মানের সাথে সামঞ্জস্যপূর্ণ কোনও প্রকারের যোগ্য সংস্করণ,
- একটি প্রকার যা বস্তুর কার্যকর ধরণের সাথে সম্পর্কিত স্বাক্ষরিত বা স্বাক্ষরযুক্ত প্রকার,
- এমন একটি প্রকার যা বস্তুর কার্যকর ধরণের কার্যকর সংস্করণের সাথে স্বাক্ষরযুক্ত বা স্বাক্ষরযুক্ত প্রকার,
- একটি সামগ্রিক বা ইউনিয়ন প্রকার যা এতে অন্তর্ভুক্ত থাকে এর সদস্যদের মধ্যে পূর্বোক্ত ধরণেরগুলির (অন্তর্ভুক্ত, পুনরাবৃত্তভাবে, একটি সাবগ্রেগেট বা সমন্বিত ইউনিয়নের সদস্য সহ), বা
- একটি চরিত্রের প্রকার।

এই ক্ষেত্রে (ছাড়া restrict), আপনি সর্বদা 121ফলাফল হিসাবে পাবেন ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.