In rpc.h, the GUID structure is declared as follows:
typedef struct _GUID
{
DWORD Data1;
WORD Data2;
WORD Data3;
BYTE Data[8];
} GUID;
I understand Data1, Data2, and Data3. They define the first, second, and third sets of hex digits when writing out a GUID (XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX).
What I never understood was why the last 2 groups were declared together in the same byte array. Wouldn't this have made more sense (and been easier to code against)?
typedef struct _GUID
{
DWORD Data1;
WORD Data2;
WORD Data3;
WORD Data4;
BYTE Data5[6];
} GUID;
Anyone know why it is declared this way?
It's because a GUID is a special case of a UUID. For information on what all the fields mean, you can look at RFC 4122.
http://en.wikipedia.org/wiki/Globally_Unique_Identifier and http://www.opengroup.org/onlinepubs/9629399/apdxa.htm (DCE's orginal representation, you can see the grouping of bits there in a table)
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I'm confused in understanding how pointers to char work.
What is the difference between using char *s = "car"; and s = "India";?
And what about char **s?
How will these be stored?
String literals like "car" and "India" are stored in arrays of character type such that they are available over the lifetime of the program. Under most circumstances, when an expression of array type appears in the code, it is implicitly converted ("decays") to an expression of pointer type, and the value of the expression is the address of the first element of the array.
So suppose our "car" string is stored as an array of char starting at address 0x8000:
+---+
0x8000: |'c'|
+---+
0x8001: |'a'|
+---+
0x8002: |'r'|
+---+
0x8003: | 0 |
+---+
When you write
char *s = "car";
the expression "car" is converted from type "4-element array of char" to "pointer to char", and the value of the expression is the address of the first element - 0x8000. So, that 0x8000 address is written to s1:
+--------+
s: | 0x8000 |
+--------+
Later on, when you write
s = "India";
the address of the first element of the array that stores "India" is written to s.
Here's a practical example. I've written a small utility that prints out the addresses and contents of multiple variables. Here's the code:
#include <stdio.h>
#include "dumper.h"
int main( void )
{
char *s = "car";
char *names[] = { "s", "\"car\"", "\"India\"" };
void *addrs[] = { &s, "car", "India" };
size_t sizes[] = { sizeof s, sizeof "car", sizeof "India" };
dumper( names, addrs, sizes, 3, stdout );
s = "India";
dumper( names, addrs, sizes, 3, stdout );
return 0;
}
Here's how it looks on my system - first we look at the strings themselves:
"car" 0x104f2ff71 63 61 72 00 car.
"India" 0x104f2ff88 49 6e 64 69 Indi
0x104f2ff8c 61 00 00 00 a...
The string "car" is stored starting at address 0x104f2ff71, and the string "India" is stored starting at address 0x104f2ff88.
Now we look at s:
s 0x7ffeeacd0a10 71 ff f2 04 q...
0x7ffeeacd0a14 01 00 00 00 ....
s is stored starting at address 0x7ffeeacd0a10, and it's contents are the address of the string literal "car". Since x86 is little-endian, multi-byte values have to be read right-to-left.
After we write
s = "India";
our memory looks like this:
s 0x7ffeeacd0a10 88 ff f2 04 ....
0x7ffeeacd0a14 01 00 00 00 ....
Now s is storing the address of the array containing "India".
what is char **s? How it will be stored?
You can have pointers to pointers:
char **s2 = &s;
s2 just stores the address of the variable s. Pointers to pointers come up when you're dealing with arrays of pointers, or when you're passing a pointer to a function and you want the function to be able to write a new pointer value.
Different pointer types may have different representations - the only guarantees are:
char * and void * have the same representation and alignment;
pointers to qualified types have the same representation and alignment as pointers to the corresponding unqualified type (i.e., int * and const int * are stored the same way);
All struct pointer types have the same representation and alignment;
All union pointer types have the same representation and alignment;
So it's possible for a char ** object to be stored differently from a char * object. On most modern systems like x86, all pointer types are stored the same way, but there are oddballs out there where that's not the case.
In a declaration, the * operator is simply part of the type; it is not dereferencing anything. We're storing the value to s, not to what s points to.
1st case
char* s = "car";
In this case you declaring a char pointer and at the same time assigning it a string literal, in other words, making it point to the beginning of the string literal.
2nd case
char* s;
//some code;
s = "india";
This is the same as first, the difference is that you are first declaring the pointer, and later assigning it the string literal.
3rd case
char** s;
Is a pointer to a pointer to char or double pointer to char, take this sample:
#include <stdio.h>
int main()
{
char* ptr1 = "abc";
char** ptr2;
ptr2 = &ptr1;
printf("%s", *ptr2);
}
Thhis means that ptr2 is pointing to ptr1 pointer to char (so it's a pointer to pointer to char), through indirection ptr2 can be used to access the beggining of the string pointed by ptr1.
Output
abc
Where the string literal is stored varies deppending on the platform, this answer has some details, as does the link I provided for string literal documentation.
String literals are not modifiable (and in fact may be placed in read-only memory such as .rodata). If a program attempts to modify the static array formed by a string literal, the behavior is undefined.
char *s = "car"; and s = "India"; are the same thing except for the fact that char *s = "car"; defines (creates) a new s variable which didn't exist before, while s = "India"; reuses the existing s. In both cases s is a variable pointer to the first character of the string which is created in a non writable part of the data space. i.e. You can change s to another string (e.g. set it to "India" or increment it), but you cannot change the pointed memory (e.g. you can't do s[0]='e').
char **p; just defines a pointer to a pointer (to a string), so you could write p=&s; and if you then wrote *p="Terminator"; s would now point to a new "terminator" string.
There is another case that you should compare with the first two, which is char s[20] = "Hello"; In this case, s is not a variable but a constant pointer to a variable 20 bytes space, in which you have stored "Hello\0". In this case, you CANNOT point s to another string as in s="turlututu";, but you can change the content of the 20 bytes space, providing you do not overflow outside this space and keep the content properly terminated with a '\0' (not terminating your string is not a syntax error, but it is a dangerous practice).
I want to print my string variable using printf method:
id = 6415F1BF713C
Serial.printf("id: %s\n\n", id);
Serial.print(id);
The result that I got was:
id: ⸮⸮⸮?
6415F1BF713C
is there any thing that's wrong?
Thanks.
Update :
//get device id
String getDeviceID() {
uint64_t chipid = ESP.getEfuseMac(); // The chip ID is essentially its MAC address(length: 6 bytes).
uint16_t chip = (uint16_t)(chipid >> 32);
char devID[40];
snprintf(devID, 40, "%04X%08X", chip, (uint32_t)chipid);
return devID;
}
String id = getDeviceID();
Serial.printf("id: %s\n\n", id);
Serial.print(id);
You didn't offer enough code to properly debug this, but I'm guessing what you mean is
String id = "6415F1BF713C";
Serial.printf("id: %s\n\n", id);
Serial.print(id);
The %s format in the printf() method expects to take a C/C++ char *, not a String. When you passed it a String, it printed the memory address of the String object - four characters which would appear as garbage, as you saw.
C and C++ use char * (pointers to characters) and char [] (arrays of characters) to represent strings. These are different from the Arduino String class, and people often confuse them.
To use the printf() method with a String you need to get its C string pointer, like this:
Serial.printf("id: %s\n\n", id.c_str());
The reason that this:
Serial.print(id);
works is that the print() method has a form that specifically expects to take a String object as an argument.
I know what pointers are but when it comes to strings/arrays I get really confused. If someone has an answer or a website that explains it that would be great. For example:
char * strncopy (char*dest, char * source, size_t);
Why the pointer? what is it pointing to? Does it a pointer usually store an address?
It is sayed in my textbook that each string building function is of type pointer char*.
Also I was trying to see if I could write a program that would clear things up, but it didn't work. Can someone tell me how to fix it, or what I'm doing wrong.
#include <stdio.h>
#include <string.h>
char * getname ()
{
char name [10];
scanf ("%s", name);
return (name);
}
int main (void)
{
char name[10];
printf ("Enter your name\n");
name[] = getname();
printf ("Hi %s", name);
return (0);
}
Inside of your getname function, when you return a pointer to the name array because it's allocated on the stack it gets destroyed leaving you with an invalid pointer. Dereferencing such a pointer causes many, many problems.
You should allocate the name array inside of getname on the heap, with malloc/calloc so that when you return the pointer the data won't be destroyed.
With regards to functions like strncpy, they tend to return a pointer to the resulting string; e.g.: strncpy returns a pointer to the destination.
Pointer itself represents an address, e.g. if you have a pointer typed char *pstr, you can always check the underlying address with printf("address of my pointer %p\n", pstr);
In C programming language, a string is an array of char. If you have a good knowledge of array and its memory layout, it's not too hard for you to understand c-styled string. Generally speaking, an array in C is a continuous chunk of memory with name of array represent address of the first element in the array. So is string who is a chunk of memory with name of the char array address of the first character. In addition, c-styled string terminates with character \0, so if you want to manage memory for string yourself, remember one extra byte for the tailing \0.
As to your second problem, your name in function getname is a local variable whose life time ends when function returns. However, you still want to access name outside the function which is inappropriate. You can solve this be dynamically allocated memory like in dasblinkenlight's and others' post.
Good luck.
Which of the following two approches is more efficient on an ATmega328P?
unsigned int value;
unsigned char char_high, char_low;
char_high = value>>8;
value = value<<8;
char_low = value>>8;
OR
unsigned int value;
unsigned char char_high, char_low;
char_high = value>>8;
char_low = value & 0xff;
You really should measure. I won't answer your question (since you'd benefit more from measuring than I would), but I'll give you a third option:
struct {
union {
uint16_t big;
uint8_t small[2];
};
} nums;
(be aware of the difference between big endian and little endian here)
One option would be to measure it (as has already been said).
Or, compile both and see what the assembly language output looks like.
but actually, the 2nd code you have won't work - if you take value << 8 and assign it to a char, all you get is zero in the char. The subsequent >>8 will still leave you with zero.
I have a legacy library that takes data from hardware and writes it to ostream.
The method looks like following :
int sensors(ostream*) const;
I am not skilled enough in Ancient Ways. How to convert this data to QByteArray? Or, at least, to char array of known size?
I would have solved it myself, but there is an additional problem: the data in ostream seem to be arbitrary length and have several arbitrary '\0' symbols, so you can't count on it being null-terminated.
I think this is what OrcunC was getting at:
std::stringstream s;
sensors( &s );
QByteArray( s.str().data(), (int) s.str().size() );
... but hopefully more clear :). See also std::stringstream and std::string for information on the classes/member functions used here. By the way, note that I am using str().data(), not str().c_str() -- I'm being really careful to handle those \0 characters, and I'm not assuming NULL termination.
I have not tried it, but you need something like this :
ostream s (ios::out | ios::binary);
//..Populate the stream
//Convert it to string. string can hold \0 values too.
string str = s.str ();
QByteArray ba (str.data (),str.size ());
You can subclass std::ostream and use an object of the subclass to collect the bytes into your QByteArray.
/**
* This helper class collects bytes that are passed to it
* into a QByteArray.
*
* After https://stackoverflow.com/a/19933011/316578
*/
class QByteArrayAppender : public std::ostream, public std::streambuf {
private:
QByteArray &m_byteArray;
public:
QByteArrayAppender(QByteArray &byteArray)
: std::ostream(this),
std::streambuf(),
m_byteArray(byteArray) {
}
int overflow(int c) {
m_byteArray.append(static_cast<char>(c));
return 0;
}
};
This avoids going via an std::string, which is an extra copy of the byte array.