নেগেটিভ অ্যারে সূচকগুলি কি সি তে অনুমোদিত?


115

আমি কেবল কিছু কোড পড়ছিলাম এবং দেখতে পেলাম যে ব্যক্তিটি এর arr[-2]আগে 2 তম উপাদানটি অ্যাক্সেস করতে ব্যবহার করছে arr:

|a|b|c|d|e|f|g|
       ^------------ arr[0]
         ^---------- arr[1]
   ^---------------- arr[-2]

এটা কি অনুমোদিত?

আমি জানি যে arr[x]একই *(arr + x)। সুতরাং arr[-2]হয় *(arr - 2)যা ঠিক আছে বলে মনে হয়। আপনি কি মনে করেন?

উত্তর:


168

ঐটা ঠিক. সি 99 §6.5.2.1 / 2 থেকে:

সাবস্ক্রিপ্ট অপারেটরের [। Nition] হ'ল E1 [E2] (* ((E1) + (E2))) এর সাথে সমান।

কোন যাদু নেই। এটি 1-1 সমতুল্য। একটি পয়েন্টার (*) কে ডিফারেন্স করার সময় সর্বদা হিসাবে আপনার অবশ্যই নিশ্চিত হওয়া উচিত যে এটি কোনও বৈধ ঠিকানার দিকে নির্দেশ করছে।


2
এটিও নোট করুন যে আপনাকে ইউবি পাওয়ার জন্য পয়েন্টারটিকে অবজ্ঞা করতে হবে না। ফলাফলটির somearray-2শুরু থেকে somearrayশেষের শেষ পর্যন্ত 1 টির মধ্যে না থাকলে কেবল কম্পিউটিং অপরিজ্ঞাত হয় ined
RBerteig

34
পুরানো বইগুলিতে পয়েন্টার পাটিগণিতের জন্য সিনট্যাক্স চিনির[] হিসাবে উল্লেখ করা হত । নবীনদের বিভ্রান্ত করার প্রিয় উপায় হ'ল পরিবর্তে - লিখতে এবং তাদের অর্থ কী তা বোঝাচ্ছে তা অনুমান করে তাদের দেখে। 1[arr]arr[1]
ডমি 00001

4
You৪ বিট সিস্টেমে (এলপি )৪) কী ঘটে যখন আপনার কাছে ৩২ বিট ইন্ট ইনডেক্স থাকে যা নেতিবাচক? ঠিকানার গণনার আগে সূচিটি কি 64 বিট স্বাক্ষরিত ইনটকে উন্নীত করা উচিত?
পল আর

4
@ পল, §§..5..6 / ৮ (অ্যাডিটিভ অপারেটর) থেকে, "যখন কোনও সংজ্ঞাটি সংখ্যার সাথে যুক্ত হয় বা পয়েন্টার থেকে বিয়োগ করা হয়, তখন ফলাফলটি পয়েন্টার অপারেণ্ডের ধরণের হয় If একটি অ্যারে অবজেক্টের এবং অ্যারে যথেষ্ট বড়, ফলাফলটি মূল উপাদান থেকে অফসেট হওয়া কোনও উপাদানকে নির্দেশ করে যেমন ফলাফল এবং মূল অ্যারের উপাদানগুলির সাবস্ক্রিপ্টগুলির পার্থক্য পূর্ণসংখ্যার ভাবের সমান হয়। " সুতরাং আমি মনে করি এটি প্রচারিত ((E1)+(E2))হবে এবং প্রত্যাশিত মান সহ একটি (64৪-বিট) পয়েন্টার হবে।
ম্যাথু ফ্ল্যাশেন

@ ম্যাথুজ: এর জন্য ধন্যবাদ - মনে হচ্ছে এটির পক্ষে যেমনটি আশা করা যায় তেমন কাজ করা উচিত
পল আর

63

এটি কেবলমাত্র বৈধ যখন arrকোনও পয়েন্টার যা একটি অ্যারে বা পরবর্তী উপাদানগুলিতে দ্বিতীয় উপাদানকে নির্দেশ করে। অন্যথায়, এটি বৈধ নয়, কারণ আপনি অ্যারের সীমানার বাইরে মেমরি অ্যাক্সেস করতে পারবেন। সুতরাং, উদাহরণস্বরূপ, এটি ভুল হবে:

int arr[10];

int x = arr[-2]; // invalid; out of range

তবে এটি ঠিক থাকবে:

int arr[10];
int* p = &arr[2];

int x = p[-2]; // valid:  accesses arr[0]

তবে এটি নেতিবাচক সাবস্ক্রিপ্ট ব্যবহার করা অস্বাভাবিক।


আমি এটি এতদূর অবধি বলতে যাব না যে এটি অবৈধ, কেবল সম্ভাব্য অগোছালো
ম্যাট জয়েনার

13
@ ম্যাট: প্রথম উদাহরণের কোডটি অনির্ধারিত আচরণ দেয়।
জেমস ম্যাকনেলিস 13:40

5
এটি অবৈধ। সি স্ট্যান্ডার্ড দ্বারা এটির স্পষ্টরূপে অপরিবর্তিত আচরণ রয়েছে। অন্যদিকে, যদি int arr[10];এটির আগে অন্য উপাদানগুলির সাথে কোনও কাঠামোর অংশ ছিল, arr[-2]সম্ভাব্যরূপে ভাল-সংজ্ঞায়িত করা যেতে পারে এবং আপনি এটি নির্ধারণ করতে পারেন offsetof, ইত্যাদি ইত্যাদি
আর .. গিথহাব স্টপ হেল্পিং আইসিই

4
এটি শেষের দিকে কেএন্ডআর বিভাগ 5.3 এ খুঁজে পেয়েছে: If one is sure that the elements exist, it is also possible to index backwards in an array; p[-1], p[-2], and so on are syntactically legal, and refer to the elements that immediately precede p[0]. Of course, it is illegal to refer to objects that are not within the array bounds.তবুও, আপনার উদাহরণটি এটি বুঝতে আমাকে সহায়তা করার জন্য আরও ভাল। ধন্যবাদ!
কিয়াং শো

4
থ্রেড নেক্রোমেন্সির জন্য দুঃখিত, তবে আমি কেবল ভালবাসি যে কে ওআরআর "অবৈধ" এর অর্থ কীভাবে অস্পষ্ট। শেষ বাক্যটি এটিকে শব্দ করে তোলে যেন সীমানার অ্যাক্সেসগুলি সংকলনের ত্রুটি ফেলে দেয়। সেই বইটি নতুনদের জন্য বিষ।
মার্টিন

12

আমার ভাল লাগছে। এটি আপনার ক্ষেত্রে বৈধভাবে প্রয়োজন হবে এমন একটি বিরল ঘটনা হবে।


9
এটা না যে বিরল - এটা আশপাশ অপারেটরদের সঙ্গে যেমন ইমেজ প্রসেসিং খুব দরকারী।
পল আর

আমার কেবল এটি ব্যবহার করা দরকার কারণ আমি একটি স্ট্যাক এবং হিপ [কাঠামো / নকশা] সহ একটি মেমরি পুল তৈরি করছি। উচ্চতর মেমরি ঠিকানার দিকে বাড়ছে স্ট্যাক, নিম্ন মেমরির ঠিকানার দিকে গাদা বাড়ছে। মাঝখানে সভা।
জেএমআই মেডিসন

8

সম্ভবত এটি কী arrঅ্যারের মাঝখানে ইশারা করছিল, অতএব arr[-2]সীমানার বাইরে না গিয়ে মূল অ্যারেতে কিছু নির্দেশ করছিল।


7

এটি কতটা নির্ভরযোগ্য তা আমি নিশ্চিত নই, তবে আমি কেবলমাত্র -৪-বিট সিস্টেমে নেতিবাচক অ্যারে সূচকগুলি সম্পর্কে সম্ভবত পড়ছি (সম্ভবত LP64): http://www.devx.com/tips/Tip/41349

লেখক মনে করছেন বলে মনে হচ্ছে যে addressing৪ বিট অ্যাড্রেসিংয়ের সাথে 32 বিট ইন্টি অ্যারে সূচকগুলি খারাপ ঠিকানা গণনার ক্ষেত্রে ফলাফল তৈরি করতে পারে যদি না অ্যারে সূচকটি স্পষ্টভাবে 64 বিটগুলিতে উন্নীত করা হয় (উদাহরণস্বরূপ একটি পিটিআরডিফ_t কাস্টের মাধ্যমে)। আমি জিসিসি ৪.১.০ এর পাওয়ারপিসি সংস্করণ সহ তার প্রকৃতির একটি বাগ দেখতে পেয়েছি, তবে আমি জানি না এটি কোনও সংকলক বাগ (যেমন C99 স্ট্যান্ডার্ড অনুযায়ী কাজ করা উচিত) বা সঠিক আচরণ (যেমন সূচকে 64৪ এ কাস্ট লাগবে) সঠিক আচরণের জন্য বিটস)?


3
এটি একটি সংকলক বাগের মতো শোনাচ্ছে।
টিবলার

2

আমি জানি প্রশ্নের উত্তর হয়েছে, কিন্তু আমি এই ব্যাখ্যাটি ভাগ করে নিতে পারিনি।

আমি কম্পাইলার ডিজাইনের মূলনীতির কথা মনে করি, আসুন ধরে নেওয়া যাক যে এটি একটি ইনট অ্যারে এবং ইন্টের আকার 2, এবং এর জন্য বেস ঠিকানা 1000 হয় is

কিভাবে a[5]কাজ করবে ->

Base Address of your Array a + (index of array *size of(data type for array a))
Base Address of your Array a + (5*size of(data type for array a))
i.e. 1000 + (5*2) = 1010

এই ব্যাখ্যার কারণেই অ্যারেতে নেতিবাচক সূচকগুলি সি-তে কাজ করে reason

আমি যদি a[-5]এটি অ্যাক্সেস করি তবে তা আমাকে দেবে

Base Address of your Array a + (index of array *size of(data type for array a))
Base Address of your Array a + (-5 * size of(data type for array a))
i.e. 1000 + (-5*2) = 990

এটি 990 অবস্থানে আমার আপত্তিটি ফিরিয়ে দেবে this এই যুক্তি দ্বারা আমরা সিটিতে অ্যারেতে নেতিবাচক সূচীগুলি অ্যাক্সেস করতে পারি


2

কেউ কেন নেতিবাচক সূচকগুলি ব্যবহার করতে চান সে সম্পর্কে, আমি সেগুলি দুটি প্রসঙ্গে ব্যবহার করেছি:

  1. সংযুক্ত সংখ্যার একটি টেবিল থাকা যা আপনাকে চিরুনি [1] [- 1] = 0; আপনি টেবিলটি অ্যাক্সেস করার আগে সর্বদা সূচকগুলি পরীক্ষা করতে পারেন তবে এই পদ্ধতিটি কোডটি আরও পরিষ্কার দেখায় এবং দ্রুত কার্যকর করে।

  2. একটি টেবিলের শুরুতে একটি সেন্টিনেল লাগানো। উদাহরণস্বরূপ, আপনি এর মতো কিছু ব্যবহার করতে চান

     while (x < a[i]) i--;

তবে তারপরে আপনার এটিও iইতিবাচক কিনা তা পরীক্ষা করা উচিত ।
সমাধান: এটা এত যে a[-1]হয় -DBLE_MAX, যাতে x&lt;a[-1]সবসময় মিথ্যা হবে।


0
#include <stdio.h>

int main() // negative index
{ 
    int i = 1, a[5] = {10, 20, 30, 40, 50};
    int* mid = &a[5]; //legal;address,not element there
    for(; i < 6; ++i)
    printf(" mid[ %d ] = %d;", -i, mid[-i]);
}

1
এই কোডটি প্রশ্নের উত্তর দিতে পারে, কেন এবং / অথবা এই কোডটির প্রশ্নের উত্তর কীভাবে তার দীর্ঘমেয়াদী মানকে উন্নত করে সে সম্পর্কে অতিরিক্ত প্রসঙ্গ সরবরাহ করে।
εηοιτ.εηοιτ.βε

পাইথন গ্রোভি একটি সাধারণ ব্যবহারের ক্ষেত্রে হ'ল অ্যারের আকারটি না জেনে কোনও অ্যারের শেষ উপাদানটি অ্যাক্সেস করতে পারে, এটি অনেক প্রকল্পের পরিস্থিতিতে একটি বাস্তব সত্য। এছাড়াও অনেক ডিএসএল এতে উপকৃত হয়।
রথিনাভেলু মুথালিয়র
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.