I have a function in visual c++ something like this:
DoSomething(IVector<unsigned char>^ inputBytes)
which is used to pass a byte array. And in this method i need to access a method of C class which accepts the byte array paramter(inputBytes). I have placed method like this in C class
void TestFunction(unsigned char* testdata[])
but it throws an error.What is the syntax of the byte array in c. How to pass this bytearray from c++ to c. Can anyone please help me to find the solution.
You declared array of pointers to char in your C function. I don't know C++/CLI, so not sure at all, but correct is one of these, I think:
void TestFunction(unsigned char* testdata)
or for many purposes exactly equal (subtle differences only):
void TestFunction(unsigned char testdata[])
First is pointer to char, or some number of chars, such as C style string. Second is array of some number of chars, which in C is almost same as pointer to char.
Most likely you need to add an int parameter, telling number of bytes, as C arrays do not know their own size (they are basically glorified pointers, as I said above), unless you can know the size some other way (like C strings end at first 0 byte).
Related
I'd like to have an array of fixed length strings in c in the form of a pointer so I can dynamically allocate the memory for it.
I can see plenty of reference to arrays of pointers to string, but not to what I want to achieve.
What I want is to be able to declare a pointer to char[MAX_STRING_LENGTH] so I can then dynamically allocate a contiguous block of memory for all the strings:
char *(names[MAX_STRING_LENGTH]); // This won't work
names = (some cast)malloc(NUM_STRINGS * MAX_STRING_LENGTH);
And then access the array of strings:
strcpy(name, names[stringIndex]);
How do I declare the variable and cast the pointer from malloc?
You declare names as an array of pointers, not a pointer to arrays. That would be
char (*names)[MAX_STRING_LENGTH]; // Names is a pointer to an array of char
Now you can allocate memory for the pointer:
// Allocate memory for NUM_STRINGS arrays and assign the pointer to names
names = malloc(NUM_STRINGS * sizeof *names);
You want a pointer to array MAX_LENGTH of char Using cdecl (note that cdecl doesn't understand things like MAX_LENGTH so we use a number here instead):
% cdecl
Type `help' or `?' for help
cdecl> declare names as pointer to array 256 of char;
char (*names)[256]
we get that the proper declaration is
char (*names)[MAX_LENGTH];
However this still isn't very useful, because reallocation would be very costly because it possibly could have to move each and every string to a new location. So I suggest that you'd still use a pointer to pointer to char.
Someprogrammerdude already provided the solution.
Generally, since C/C++ types can become somewhat tricky, you can utilize any half-decent IDE to look up correct type definitions.
This trick relies on the C++11 auto keyword, which determines a variable type from its initializer. The resulting type can still be used in other C/C++ versions and is not restricted to C++11.
In your case, specify a type that you know and that can be transformed into the type you want:
char names[10][10];
Then assign an auto variable with the desired type:
auto names2 = &names[0];
Inspect the actual type of names2 and use it. For example, in Visual Studio, just hover the mouse over names2 to see the type. Most IDEs will display the type by hovering over either the auto keyword or the defined variable.
For the example, hovering would reveal the type char (*names2)[10].
You need to understand the concept of Pointer Arrays.Refer the book "The C programming Language" By Dennis M. Ritchie & Kernighan. Specially the pointer and array part.There are some amazing stuffs to read. Probably you will get a more deeper concept of pointers and arrays after reading and solving some problems given in the book.
strlen() considers that '\00' is end of the string. How to calculate real length? E.g. there is AnsiString type in Pascal. It can contain many #$00 , but Length(s) will give correct result. Debugging of compiled pascal code shows that pascal puts length to dword before first element (#s[0] - 4) and recalculate it for me if needed. Is there something the same in C language (or I must manually to allocate memory and take care of -1 - element)? If no, C language is much worse than Pascal.
The C standard says that strings end with a NUL character. The string may be stored in an array that is larger than that, but there is no way to get the size of an array if you are only given a pointer to the array.
#include <stdio.h>
void f(char *s)
{
printf("%s\n", s);
// you can't get the size of array s here
}
int main(void)
{
char s[100] = "hi";
printf("size of s = %zu\n", sizeof(s)); // this works
f(s);
return 0;
}
Question
Is there something the same in C language?
No, there is nothing like that in C or the standard C library. However, the language provides the building blocks to define such a type and create API functions to work on the type.
Something like:
typedef struct AnsiString
{
size_t len;
char* data;
} AnsiString;
AnsiString createAnsiString(size_t len)
{
AnsiString s;
s.len = len;
s.data = malloc(len);
return s;
}
void deleteAnsiString(AnsiString s)
{
free(s.data);
}
Then you can use
AnsiString s = createAnsiString(10);
// Use s as you please
deleteAnsiString(s);
The biggest problem with this question is that a string isn't considered a 'type' in C. It's a pattern of values... Think about integers that are multiples of ten, for example. They all end in 0, yet you can store them in any type of integer providing they're in range. Strings are similar; you can store them in arrays of char, signed char, wchar_t, etc. They're not types, though... They're values that fit a specific pattern.
That pattern is similar to the "multiples of ten" I described above: A string is a sequence of digits that ends at the first '\0'. If there is no NUL character, it's not a string. It's just a sequence of characters.
If you want the size of the array, and the array hasn't yet been converted to a pointer type, you can use sizeof array because the array still carries the size information. However, once the array is converted to a pointer (when calling a function with the array identifier as an argument, as a common example) you need to manually carry the size information. Standard functions commonly use separate size arguments as a result, for example fgets(array, sizeof array, stdin);.
Whether you consider C to be better or worse than Pascal is a matter of opinion, and you have one good point. The main point of Pascal vs. C is ease of developing a compiler, which you'll discover if you ever try to write one (a great way of learning everything about the language, btw).
However, in the grand scheme of things this is only a small part of a larger issue, which Pascal also mostly suffers from. If you're going into the business of comparing programming languages based on ability to write expressive code, you might find this article ranking programming languages on expressive power to be useful.
Best of luck with your language studies :) It's nice to see people developing code that uses the maximum expressive potential of a language.
This question already has answers here:
Length of array in function argument
(9 answers)
Closed 8 years ago.
I have a question about loop through array using pointer, for example:
bool loopArray(int* array)
{
/*for(){}*/
}
within this function, I need to loop through this array without known the size of the array, how to loop it?
You can't.
Errrm, that's it.
You either provide a size parameter:
bool loopArray(int* array,size_t sz)
{
for(size_t i=0;i<sz;++i){
//Do stuff with array[i]....
}
}
Or a pointer to the 'end' of the array. You're allowed to point to one past the end and convention is to pass one-past-the-end as end. That allows you to specify 'empty' when begin==end:
bool loopArray(int* array,int* end)
{
for(;array!=end;++array){
//Do stuff with *array....
}
}
Looking at the previous example you would have defined int* end=array+sz before calling.
The second is faster and has the added benefit that other C programmers will start to recognize you as one of their own! If you see that as a benefit....
PS: For completeness: You can ensure you have a 'sentinel'. A sentinel is some value that indicates 'end'. The C standard library uses '\0' as the sentinel in character strings. Mores the pity.
That trick can work particularly when you're dealing with arrays of pointers and use NULL as the sentinel.
However it's not something to recommend as a general answer. It's error-prone, has a big overhead if you need to know the size, it restricts your ability to access 'sub-arrays' without modifying them and forbids you from using the sentinel as a value and breaks programs that do so by accident.
Other than that it's great.
it is impossible. You need some kind of information about the size; otherwise you will inevitabilly go past its borders...
A pointer doesn't "contain" any information about the size of the array that was allocated; it only points to a place in memory.
EXCEPT
There might be a way around; if you know what is the last element in your array (which MUST always be present then). This is used for example in char arrays (where the last element is \0)
You can't.
But you could do something on the lines of how the C standard library models strings. Given a char*, or a const char*, functions like strlen stop once 0 is reached (known as the null terminator).
So (i) either reserve an int value which acts as your terminator, or (ii) pass the length.
Either way, pass a const int* if you don't intend to modify the contents.
I am trying to pass a character pointer array as an input from C test driver to C++ function (available in C wrapper)
char* LowerList[10];
LowerList[0]="abc";
LowerList[1]="def";
LowerList[2]="hij";
When available on the C++ side the values displayed for the the element is displayed as
char* LowerList[0]="abc";
LowerList[1]="def";
LowerList[2]="hij";
LowerList[3]=ƒì¶S<\$ UV<35?Ä#
LowerList[34]=ƒ<bad pointer>
I need to get the size of the array passed on to the C++ size which I could have got using
while (LowerList[count]) but unable to do so because of the junk value.
Please let me know if any way I can find the correct size of the char* LowerList[] by initialising ,memory allocation or converting it to vector.
Corrected the above code for typo error
Here are my comments on some of the suggestions given to me so far:
1) Pass the size of the array as a parameter as well- A limitation for my scenario .2) Conversion to the vector need the size to be available 3) Sentinel value at which position I need to add . As stated earlier I am trying to handle a scenario where the user pass the value as 3 which leads to the failure.I don't have any control on restricting the way C user my C++ wrapper with his C test driver.
The pointers LowerList[3] through LowerList[9] are all uninitialized, if I'm not mistaken. You could always just use NULL as a sentinel value, and either assign it explicitly or do something like this:
char* LowerList[10] = { "abc", "def", "hij" };
This should initialize the remaining pointers in the array to NULL.
In response to your second comment:
#define LOWER_LIST_SIZE 10
#define MINIMUM_SIZE 2
#if LOWER_LIST_SIZE < MINIMUM_SIZE
#error "LOWER_LIST_SIZE must be >= MINIMUM_SIZE"
#endif
char *LowerList[LOWER_LIST_SIZE] = // etc.
Or something like that.
http://en.wikipedia.org/wiki/C_preprocessor#User-defined_compilation_errors_and_warnings
Furthermore, your initialization as given is totally wrong. You have:
char* LowerList[10];
char* LowerList[0]="abc";
char* LowerList[1]="def";
char* LowerList[2]="hij";
What you want is:
char* LowerList[10];
LowerList[0]="abc";
LowerList[1]="def";
LowerList[2]="hij";
or the alternative that JAB has. The issue with your version is that you are essentially declaring LowerList 4 times, but you can't do that.
I am having a VB application request a list of users from a C DLL:
VB will ask the DLL how many users there are, and then initialize an array to the appropriate size.
VB will then pass its array by reference to a DLL function, which will fill it with usernames.
I started writing the C function like this: foo(char **bar); which would be treated as an array of strings. But then I realized, I'm going to make each item in the array point to a different C-string (the char *username in the struct userlist linked list) rather than modify the data already being pointed to. The array of arrays is being passed by value: a copy of a list of addresses, so the addresses point to the original data, but modifying the addresses in that copy won't change the list of addresses of the caller (I think, anyways). So, should I be declaring it foo(char ***bar);? This would be a pointer to the array of strings, so that if I change the strings that array is pointing to, it will modify the array of strings the caller (VB) is using....right?
This is my usage so far (haven't tested it yet... I'm still just coding the DLL as of yet, there's no VB front-end to call it thus far)
EXPORT void __stdcall update_userlist(char ***ulist){
int i = 0;
userlist *cur_user = userlist_head; //pointer to first item in linked list
for(; i < usercount_; ++i){
*ulist[i] = cur_user->username;
cur_user = cur_user->next;
}
}
In general it's not simple to do what you're asking, because VB just doesn't understand C-style ASCIIZ strings and arrays.
If your DLL is not expecting a VB SafeArray of BSTR, you're going to have some difficulty populating it.
It would be simple to have VB pass in an array of Long (C int) by reference to the first element, and you could fill that with the pointers to individual strings. The VB side could copy them to VB strings. But in that case, who disposes of the C strings, and when?
If you create the VB array and fill it with pre-sized strings, you'll still have to deal with a SafeArray on the C side, because you can't pass a single VB string array element by reference and expect to find the remaining strings contiguous to it in memory.
The best, safest method is to have your DLL create a SafeArray of so-called 'Ansi BSTR', and declare the function in VB as returning an array of strings. Then you don't need two calls, because the array bounds will tell the whole story.
===== edit =====
When VB passes a string array to a Declared function it does some voodoo behind the scenes. It first converts all the strings from Unicode to a bastard form commonly known as 'Ansi BSTR'. To C, these look like and can be treated as ASCIIZ or LPSTR except that you can't create or lengthen them in the normal C way, you can only fill them in. On the C side, the passed array looks like ppSA (SAFEARRAY**). The Ansi BSTR are a series of pointers referenced by the pData member of the SafeArray.
You absolutely cannot pass a single string from the array (as char*) and expect to find the rest of the strings contiguous to it in memory. You have to pass the array itself and manipulate it using the SafeArray API (or knowledge of the SA structure).
That's why the best option overall is to do all of this directly in the DLL. Create the array using SafeArrayCreate, then create Ansi BSTRs using SysAllocStringByteLen and place those strings (which are BSTR, so a 4-byte pointer) into the array slots. On return, VB does its voodoo and converts the strings to Unicode for you.
In VB your function would be Declared as returning a String().
two asterixes is the way to go.
char* // is a pointer to a char
char** // is a pointer to a char pointer
char*** // is a pointer to a pointer to a char pointer - e.g. multi-dimensional array (err...)
I've confused myself :)
So let me get this straight. Your function fills in an array of strings from data contained in a linked list ?
If you know the size of the list beforehand, you can just pass a char **, but if you do not know the size and need to be able to grow the list, you will need a char ***.
From looking at your code, you seem to already know the length, so you just need to allocate an array of the correct length before you call the function. Here is an example:
void update_userlist(char **ulist)
{
int i = 0;
userlist *cur_user = userlist_head;
for(; i < usercount_; ++i)
{
ulist[i] = cur_user->username; // I am assuming that username is a char *
cur_user = cur_user->next;
}
}
// This sets up the array and calls the function.
char **mylist = malloc(sizeof(char*) * usercount_);
update_userlist(mylist);
Update: Here is the difference between the various levels of pointers:
void func1(char *data)
This passes a copy of a pointer to a C string. If you change the pointer to point to a different string, the calling function will still point to the original string.
void func2(char **data)
This passes a copy of a pointer to an array of pointers to C strings. You can replace the pointer to any string in the array and the calling function's array will be changed because it has not made a copy of the array, it only points to the caller's array.
void func3(char ***data)
This passes a pointer to a pointer to an array of pointers to C strings. With this, you can completely replace the entire array. You would only need this level of indirection if you need to grow the array since C arrays cannot be re-sized.