আমি কেন স্ট্যাক অ্যারের জন্য পয়েন্টারটিতে পয়েন্টার অ্যাক্সেস করতে পারি না?


35

দয়া করে নীচের কোডটি একবার দেখুন। এটি char**কোনও ফাংশনে একটি অ্যারে পাস করার চেষ্টা করে:

#include <stdio.h>
#include <stdlib.h>

static void printchar(char **x)
{
    printf("Test: %c\n", (*x)[0]);
}

int main(int argc, char *argv[])
{
    char test[256];
    char *test2 = malloc(256);

    test[0] = 'B';
    test2[0] = 'A';

    printchar(&test2);            // works
    printchar((char **) &test);   // crashes because *x in printchar() has an invalid pointer

    free(test2);

    return 0;
}

এটা সত্য যে আমি শুধু এটা স্পষ্টভাবে কাস্ট করে কম্পাইল পেতে পারেন &test2করতে char**ইতিমধ্যে ইঙ্গিত এই কোড ভুল।

তবুও, আমি ভাবছি এটি সম্পর্কে ঠিক কী ভুল। আমি একটি পয়েন্টারকে গতিশীলভাবে বরাদ্দ করা অ্যারেগুলিতে একটি পয়েন্টারটি পাস করতে পারি তবে স্ট্যাকের একটি অ্যারের জন্য আমি একটি পয়েন্টারটিতে একটি পয়েন্টারটি পাস করতে পারি না। অবশ্যই আমি প্রথমে অস্থায়ী ভেরিয়েবলকে অ্যারেটি বরাদ্দ করে সহজেই সমস্যাটি ঘটাতে পারি:

char test[256];
char *tmp = test;
test[0] = 'B';
printchar(&tmp);

তবুও, কেউ আমাকে ব্যাখ্যা করতে পারেন কেন এটি সরাসরি কাস্ট char[256]করার কাজ করে না char**?

উত্তর:


29

কারণ testপয়েন্টার নয়।

&testআপনাকে টাইপের অ্যারেতে পয়েন্টার দেয় char (*)[256], যা এর সাথে সামঞ্জস্যপূর্ণ নয় char**(কারণ একটি অ্যারে পয়েন্টার নয়)। এটি অনির্ধারিত আচরণের ফলাফল।


3
কিন্তু কেন সি কম্পাইলার তারপর টাইপ কিছু ক্ষণস্থায়ী অনুমতি দেয় char (*)[256]করার char**?
কমফ্রিচ

@ কমফ্রিচ আমি সন্দেহ করি যে সর্বাধিক সতর্কতা এবং ওয়ারার্স সহ এটি অনুমতি দেয় না।
পাইরকস

@ কমফ্রিচ: এটি সত্যিই এটির অনুমতি দেয় না। আমাকে সংকলককে স্পষ্টভাবে কাস্ট করে এটি গ্রহণ করতে বাধ্য করতে হবে char**। Castালাই ছাড়া এটি সংকলন করে না।
আন্দ্রেয়াস

38

testএকটি অ্যারে, কোনও পয়েন্টার নয়, এবং &testঅ্যারের পয়েন্টার। এটি কোনও পয়েন্টারের কাছে নির্দেশক নয়।

আপনাকে বলা হতে পারে যে অ্যারেটি পয়েন্টার তবে এটি ভুল this অ্যারের নাম হ'ল পুরো উপাদানটির নাম - সমস্ত উপাদান। এটি প্রথম উপাদানটির জন্য কোনও পয়েন্টার নয়। বেশিরভাগ অভিব্যক্তিগুলিতে একটি অ্যারে স্বয়ংক্রিয়ভাবে তার প্রথম উপাদানে পয়েন্টারে রূপান্তরিত হয়। এটি একটি সুবিধা যা প্রায়শই দরকারী। তবে এই নিয়মে তিনটি ব্যতিক্রম রয়েছে:

  • অ্যারে অপারেন্ড হয় sizeof
  • অ্যারে অপারেন্ড হয় &
  • অ্যারে একটি স্ট্রিং আক্ষরিক যা অ্যারে শুরু করার জন্য ব্যবহৃত হয়।

ইন &test, অ্যারেটি অপেরাড &, সুতরাং স্বয়ংক্রিয় রূপান্তর ঘটে না। এর ফলাফলটি &test256 এর অ্যারের প্রতি নির্দেশক char, যার টাইপ রয়েছে char (*)[256], নেই char **

একটি পয়েন্টার একটি পয়েন্টার পেতে charথেকে test, আপনাকে প্রথমে একটি পয়েন্টার করতে হবে char। উদাহরণ স্বরূপ:

char *p = test; // Automatic conversion of test to &test[0] occurs.
printchar(&p);  // Passes a pointer to a pointer to char.

এটি সম্পর্কে চিন্তা করার আর একটি উপায় হ'ল বুঝতে হবে যে testপুরো বস্তুর নাম 25 পুরো 256 এর অ্যারে char। এটি কোনও পয়েন্টারের নাম দেয় না, সুতরাং, &testএমন কোনও পয়েন্টার নেই যার ঠিকানা নেওয়া যেতে পারে, সুতরাং এটি কোনও উত্পাদন করতে পারে না char **। একটি তৈরি করতে char **, আপনার অবশ্যই প্রথমে একটি থাকা উচিত char *


1
তিনটি ব্যতিক্রমের এই তালিকা কি সম্পূর্ণ?
রুসলান

8
@ রুসলান: হ্যাঁ, প্রতি সি 2018 6.3.2.1 ৩.
এরিক পোস্টপিসিল

ওহ, এবং C11 সেখানে ছিল _Alignofঅপারেটর ছাড়াও উল্লিখিত sizeofএবং &। আমি অবাক করেছিলাম কেন তারা এটিকে সরিয়ে দিয়েছে ...
রুসলান

@ রুসলান: এটি ভুল হয়েছে বলে এটি সরানো হয়েছে। _Alignofকেবল কোনও অপারেন্ড হিসাবে কোনও প্রকারের নাম গ্রহণ করে এবং কোনও অ্যারে বা অন্য কোনও অবজেক্টকে অপারেন্ড হিসাবে গ্রহণ করে না। (কেন জানি না; এটি সিন্টেক্সিকভাবে এবং ব্যাকরণগতভাবে এটির মতো হতে পারে sizeof, তবে তা নয়))
এরিক পোস্টপিসিল

6

ধরণ test2হয় char *। সুতরাং, ধরণ &test2হতে হবে char **যা পরামিতি ধরণ সঙ্গে সামঞ্জস্যপূর্ণ xএর printchar()
ধরণ testহয় char [256]। সুতরাং, ধরণ &testহতে হবে char (*)[256]যা না পরামিতি ধরণ সঙ্গে সামঞ্জস্যপূর্ণ xএর printchar()

আমাকে আপনার ঠিকানা পরিপ্রেক্ষিতে পার্থক্য দেখাতে যাক testএবং test2

#include <stdio.h>
#include <stdlib.h>

static void printchar(char **x)
{
    printf("x = %p\n", (void*)x);
    printf("*x  = %p\n", (void*)(*x));
    printf("Test: %c\n", (*x)[0]);
}

int main(int argc, char *argv[])
{
    char test[256];
    char *test2 = malloc(256);

    test[0] = 'B';
    test2[0] = 'A';

    printf ("test2 : %p\n", (void*)test2);
    printf ("&test2 : %p\n", (void*)&test2);
    printf ("&test2[0] : %p\n", (void*)&test2[0]);
    printchar(&test2);            // works

    printf ("\n");
    printf ("test : %p\n", (void*)test);
    printf ("&test : %p\n", (void*)&test);
    printf ("&test[0] : %p\n", (void*)&test[0]);

    // Commenting below statement
    //printchar((char **) &test);   // crashes because *x in printchar() has an invalid pointer

    free(test2);

    return 0;
}

আউটপুট:

$ ./a.out 
test2 : 0x7fe974c02970
&test2 : 0x7ffee82eb9e8
&test2[0] : 0x7fe974c02970
x = 0x7ffee82eb9e8
*x  = 0x7fe974c02970
Test: A

test : 0x7ffee82eba00
&test : 0x7ffee82eba00
&test[0] : 0x7ffee82eba00

এখানে লক্ষণীয়:

আউটপুট (মেমরি ঠিকানা) test2এবং &test2[0]হয় সংখ্যাসূচকভাবে একই এবং তাদের প্রকার যা একই char *
তবে test2এবং &test2বিভিন্ন ঠিকানা এবং তাদের ধরণটিও আলাদা।
ধরণ test2হয় char *
ধরণ &test2হয় char **

x = &test2
*x = test2
(*x)[0] = test2[0] 

আউটপুট (মেমরি অ্যাড্রেস) এর test, &testএবং &test[0]হয় সংখ্যাসূচকভাবে একই কিন্তু তাদের টাইপ ভিন্ন
ধরণ testহয় char [256]
ধরণ &testহয় char (*) [256]
ধরণ &test[0]হয় char *

আউটপুট শো &testহিসাবে একই &test[0]

x = &test[0]
*x = test[0]       //first element of test array which is 'B'
(*x)[0] = ('B')[0]   // Not a valid statement

অতএব আপনি বিভাগের ত্রুটি পাচ্ছেন।


3

আপনি কোনও পয়েন্টারে পয়েন্টার অ্যাক্সেস করতে পারবেন না কারণ এটি &test এটি পয়েন্টার নয় - এটি একটি অ্যারে।

যদি আপনি কোনও অ্যারের ঠিকানা নেন তবে অ্যারে এবং অ্যারের ঠিকানাটি কাস্ট করুন (void *)এবং তাদের তুলনা করুন, তারা (সম্ভাব্য পয়েন্টার প্যাডেন্ট্রি বাদ দিয়ে) সমতুল্য হবে।

আপনি আসলে যা করছেন তা এর সাথে মিল রয়েছে (আবারও, কঠোর অ্যালিজিং বাদ দিয়ে):

putchar(**(char **)test);

যা বেশ স্পষ্টতই ভুল।


3

আপনার কোড যুক্তি আশা xএরprintchar একটি রয়েছে মেমরি বিন্দু (char *)

প্রথম কলটিতে, এটি ব্যবহৃত স্টোরেজের দিকে নির্দেশ করে test2এবং এইভাবে এটি একটি মান যা এটিকে নির্দেশ করে(char *) নির্দেশ করে যা পরে বরাদ্দকৃত স্মৃতিতে নির্দেশ করে।

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

আপনি যা চান তা পেতে, আপনাকে এটি স্পষ্টভাবে করতে হবে:

char *tempptr = &temp;
printchar(&tempptr);

আমি ধরে নিলাম আপনার উদাহরণটি কোডের অনেক বড় অংশের একটি পাতন; একটি উদাহরণ হিসাবে, সম্ভবত আপনি চান printcharবাড়াতে (char *)মান গৃহীত xVALUE পয়েন্ট যাতে পরবর্তী কল পরবর্তী অক্ষরে ছাপা হয়। যদি এটি না হয় তবে আপনি কেন (char *)মুদ্রিত হওয়ার জন্য অক্ষরটিকে কেবল একটি নির্দেশক পাস করেন না , বা এমনকি চরিত্রটি নিজেই পাস করেন না?


ভাল উত্তর; আমি এটিকে সোজা রাখার সহজতম উপায় হ'ল অ্যারের ঠিকানা হ'ল কোনও সি অবজেক্ট আছে কিনা তা নিয়ে চিন্তা করা, অর্থাত্ একটি পয়েন্টার অবজেক্ট যা আপনি একটি পাওয়ার জন্য ঠিকানাটি নিতে পারেন char **। এরে ভেরিয়েবল / কেবল বস্তু হয় অ্যারের, ঠিকানা হচ্ছে অন্তর্নিহিত না সংরক্ষণ করা যে কোন জায়গায় সঙ্গে। এগুলিতে অ্যাক্সেসের জন্য কোনও অতিরিক্ত স্তরের ইন্ডিয়ারেশন নয়, অন্য স্টোরেজকে নির্দেশ করে এমন পয়েন্টার ভেরিয়েবলের সাথে ভিন্ন।
পিটার কর্ডস

0

স্পষ্টতই, ঠিকানা testনেওয়া ঠিকানার ঠিকানা নেওয়ার মতো test[0]:

#include <stdio.h>
#include <stdlib.h>

static void printchar(char **x)
{
    printf("[printchar] Address of pointer to pointer: %p\n", (void *)x);
    printf("[printchar] Address of pointer: %p\n", (void *)*x);
    printf("Test: %c\n", **x);
}

int main(int argc, char *argv[])
{
    char test[256];
    char *test2 = malloc(256);

    printf("[main] Address of test: %p\n", (void *)test);
    printf("[main] Address of the address of test: %p\n", (void *)&test);
    printf("[main] Address of test2: %p\n", (void *)test2);
    printf("[main] Address of the address of test2: %p\n", (void *)&test2);

    test[0] = 'B';
    test2[0] = 'A';

    printchar(&test2);            // works
    printchar(&test);   // crashes because *x in printchar() has an invalid pointer

    free(test2);

    return 0;
}

এটি কম্পাইল করে চালান:

forcebru$ clang test.c -Wall && ./a.out
test.c:25:15: warning: incompatible pointer types passing 'char (*)[256]' to
      parameter of type 'char **' [-Wincompatible-pointer-types]
    printchar(&test);   // crashes because *x in printchar() has an inva...
              ^~~~~
test.c:4:30: note: passing argument to parameter 'x' here
static void printchar(char **x)
                             ^
1 warning generated.
[main] Address of test: 0x7ffeeed039c0
[main] Address of the address of test: 0x7ffeeed039c0 [THIS IS A PROBLEM]
[main] Address of test2: 0x7fbe20c02aa0
[main] Address of the address of test2: 0x7ffeeed039a8
[printchar] Address of pointer to pointer: 0x7ffeeed039a8
[printchar] Address of pointer: 0x7fbe20c02aa0
Test: A
[printchar] Address of pointer to pointer: 0x7ffeeed039c0
[printchar] Address of pointer: 0x42 [THIS IS THE ASCII CODE OF 'B' in test[0] = 'B';]
Segmentation fault: 11

সুতরাং বিভাজন ত্রুটির চূড়ান্ত কারণ হ'ল এই প্রোগ্রামটি নিখুঁত ঠিকানাটিকে 0x42(যা এটি হিসাবে পরিচিত হিসাবেও ড্রেফারেন্স করার চেষ্টা করবে)'B' যা এটি ), যা আপনার প্রোগ্রামটি পড়ার অনুমতি নেই তা ।

যদিও একটি আলাদা সংকলক / মেশিনের সাথে ঠিকানাগুলি পৃথক হবে: এটি অনলাইনে চেষ্টা করুন! , তবে আপনি এখনও এটি পাবেন, কিছু কারণে:

[main] Address of test: 0x7ffd4891b080
[main] Address of the address of test: 0x7ffd4891b080  [SAME ADDRESS!]

তবে সেগমেন্টেশন ত্রুটির কারণ ঠিকানাটি খুব ভাল হতে পারে:

[printchar] Address of pointer to pointer: 0x7ffd4891b080
[printchar] Address of pointer: 0x9c000000942  [WAS 0x42 IN MY CASE]

1
ঠিকানা testনেওয়া ঠিকানার ঠিকানা নেওয়ার মতো নয় test[0]। আগেরটির টাইপ থাকে char (*)[256], এবং শেষটির টাইপ থাকে char *। এগুলি উপযুক্ত নয় এবং সি স্ট্যান্ডার্ড তাদের বিভিন্ন উপস্থাপনা করার অনুমতি দেয়।
এরিক পোস্টপিসিল

এর সাথে পয়েন্টার ফর্ম্যাট করার সময় %pএটিতে রূপান্তর করা উচিত void *(সামঞ্জস্যতা এবং উপস্থাপনার কারণে আবার)।
এরিক পোস্টপিসিল

1
printchar(&test);আপনার জন্য ক্র্যাশ হতে পারে, কিন্তু আচরণটি সি স্ট্যান্ডার্ড দ্বারা সংজ্ঞায়িত হয়নি, এবং লোকেরা অন্যান্য পরিস্থিতিতে অন্যান্য আচরণগুলি পর্যবেক্ষণ করতে পারে।
এরিক পোস্টপিসিল

পুনরায় "সুতরাং বিভাজন ত্রুটির চূড়ান্ত কারণটি হ'ল এই প্রোগ্রামটি সর্বশেষ ঠিকানা 0x42 (এটি 'বি' নামে পরিচিত), যা সম্ভবত ওএস দ্বারা দখল করা আছে তা অবলম্বন করার চেষ্টা করবে” ": যদি কোনও সেগমেন্ট ত্রুটি পড়ার চেষ্টা করছে একটি অবস্থান, এর অর্থ সেখানে কিছুই ম্যাপ করা হয়নি, এটি ওএস দ্বারা দখল করা নয়। (সেখানে
ম্যাপযুক্ত

1
&test == &test[0]সি 2018 6.5.9 2 এ সীমাবদ্ধতা লঙ্ঘন করে কারণ ধরণের সামঞ্জস্যপূর্ণ নয়। এই মান লঙ্ঘন সনাক্তকরণের জন্য সি স্ট্যান্ডার্ডের একটি প্রয়োগকরণ প্রয়োজন এবং ফলাফলটি সি স্ট্যান্ডার্ড দ্বারা সংজ্ঞায়িত হয় না। তার অর্থ আপনার সংকলকটি তাদের সমান হতে মূল্যায়ন কোড তৈরি করতে পারে তবে অন্য সংকলকটি এটি নাও পারে।
এরিক পোস্টপিসিল

-4

এর উপস্থাপনা char [256]বাস্তবায়ন নির্ভর। এটি অবশ্যই একইরকম হওয়া উচিত নয়char *

কাস্টিং &testধরনের char (*)[256]থেকেchar ** উৎপাদনের আচরণ undefined।

কিছু সংকলক সহ, এটি আপনি যা প্রত্যাশা করেন তা করতে পারে, অন্যদের জন্য নয়।

সম্পাদনা করুন:

জিসিসি 9.2.1 এর সাথে পরীক্ষার পরে, এটি প্রদর্শিত হয় যে  মূল্যকে কাস্ট করা হিসাবে printchar((char**)&test)বাস্তবে চলে যায় । যেনো নির্দেশই ছিল । ইন ফাংশন, অ্যারে পরীক্ষা, প্রথম অক্ষর একটি ডবল পয়েন্টার প্রথম গৃহস্থালি একটি পয়েন্টার হয়। একটি দ্বৈত ডি-রেফারেন্সtestchar**printchar((char**)test)printcharxx ফলে একটি সেগমেন্টেশন ত্রুটি হয় কারণ অ্যারের 8 টি প্রথম বাইট কোনও বৈধ ঠিকানার সাথে মিল রাখে না।

9.0.0-2 বাজে সাথে প্রোগ্রামটি সংকলন করার সময় আমি ঠিক একই আচরণ এবং ফলাফল পেয়েছি get

এটি একটি সংকলক বাগ হিসাবে বিবেচনা করা যেতে পারে, বা একটি অনির্ধারিত আচরণের ফলাফল যার ফলাফল সংকলক নির্দিষ্ট হতে পারে।

আর একটি অপ্রত্যাশিত আচরণ হ'ল কোড

void printchar2(char (*x)[256]) {
    printf("px: %p\n", *x);
    printf("x: %p\n", x);
    printf("c: %c\n", **x);
}

আউটপুট হয়

px: 0x7ffd92627370
x: 0x7ffd92627370
c: A

অদ্ভুত আচরণ যে xএবং*x একই মান রয়েছে।

এটি একটি সংকলক জিনিস। আমি সন্দেহ করি যে এটি ভাষা দ্বারা সংজ্ঞায়িত করা হয়েছে।


1
আপনি কি বলতে চান প্রতিনিধিত্ব char (*)[256]বাস্তবায়ন নির্ভর? char [256]এই প্রশ্নের প্রতিনিধিত্ব প্রাসঙ্গিক নয় - এটি কেবল বিটগুলির একগুচ্ছ। তবে, এমনকি যদি আপনি বোঝাতে চান যে বিন্যাসে কোনও বিন্দুর প্রতিনিধিত্ব একটি পয়েন্টারের প্রতিনিধিত্ব থেকে একটি পয়েন্টারের কাছে পৃথক হয় তবে এটি বিন্দুটিও মিস করে। এমনকি যদি তাদের একই উপস্থাপনা থাকে তবে ওপির কোডটি কাজ করবে না, কারণ পয়েন্টারটির কাছে পয়েন্টারটি দ্বিগুণ হিসাবে বিবেচনা করা যেতে পারে printchar, তবে বিন্যাসে বিন্দু বিন্যাস ছাড়াই পারে না to
এরিক পোস্টপিসিল

@EricPostpischil থেকে কাস্ট করার char (*)[256]জন্য char **কম্পাইলার দ্বারা গৃহীত হয়, কিন্তু প্রত্যাশিত ফল না কারণ একটি char [256]একটি হিসাবে একই নয় char *। আমি ধরে নিয়েছি, এনকোডিং আলাদা, অন্যথায় এটি প্রত্যাশিত ফলাফলটি অর্জন করবে।
chmike

"প্রত্যাশিত ফলাফল" দ্বারা আপনি কী বোঝেন তা আমি জানি না। ফলাফলটি কী হওয়া উচিত তার সি স্ট্যান্ডার্ডের একমাত্র স্পেসিফিকেশনটি হ'ল, যদি প্রান্তিককরণের জন্য অপর্যাপ্ত হয় char **, আচরণটি অপরিজ্ঞাত হয়, এবং তা না হলে, যদি ফলাফলটি আবার রূপান্তরিত char (*)[256]হয় তবে এটি মূল পয়েন্টারের সমান তুলনা করে। "প্রত্যাশিত ফলাফল" দ্বারা, আপনার অর্থ হতে পারে, যদি(char **) &test আরও একটিতে রূপান্তরিত হয় তবে char *এটি এর সাথে সমান তুলনা করে &test[0]। ফ্ল্যাট ঠিকানার স্থান ব্যবহার করে এমন বাস্তবায়নের ক্ষেত্রে এটি সম্ভাব্য নয়, তবে এটি নিখুঁতভাবে উপস্থাপনের বিষয় নয়।
এরিক পোস্টপিসিল

2
এছাড়াও, "চর (*) [256] থেকে চর ** টাইপ করার কাস্টিং এবং পরীক্ষা অনির্ধারিত আচরণ দেয় s" সঠিক নয়. সি 2018 6.3.2.3 7 একটি অবজেক্ট টাইপের পয়েন্টারটিকে অন্য কোনও পয়েন্টারে কোনও অবজেক্ট টাইপের রূপান্তর করতে দেয়। যদি পয়েন্টারটি যথাযথভাবে রেফারেন্স করা টাইপের জন্য প্রান্তিক না হয় (তবে রেফারেন্স করা প্রকারের प्रकारটি char **হয় char *), তবে আচরণটি সংজ্ঞায়িত। অন্যথায়, রূপান্তরটি সংজ্ঞায়িত করা হয়েছে, যদিও উপরে আমার মন্তব্য অনুসারে মানটি আংশিকভাবে সংজ্ঞায়িত।
এরিক পোস্টপিসিল

char (*x)[256]হিসাবে একই জিনিস নয় char **x। একই পয়েন্টার মানের কারণ xএবং *xমুদ্রণ হ'ল এটি xকেবল অ্যারেতে পয়েন্টার। আপনার *x অ্যারে এবং পয়েন্টার প্রসঙ্গে এটি ব্যবহার করে অ্যারের ঠিকানার দিকে ফিরে আসে । সেখানে কোনও সংকলক বাগ (বা কী (char **)&testকরে), প্রকারের সাথে এটি চলছে তা নির্ধারণের জন্য প্রয়োজন সামান্য মানসিক জিমন্যাস্টিক required (সিডিসিএল এটিকে "চার্জের 256 অ্যারেতে পয়েন্টার হিসাবে এক্স ডিক্লেয়ার" হিসাবে ব্যাখ্যা করে)। এমনকি কোনওটির char*অবজেক্ট-প্রতিনিধিত্ব অ্যাক্সেস করতে ব্যবহার করা char**ইউবি নয়; এটি যে কোনও উপাখ্যান করতে পারে।
পিটার কর্ডেস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.