I'm having some trouble wrapping my head around how a certain line of code works. For some reason it's just not clicking. This line of code is used generally with abstracting file handles in unix domain sockets.
Context:
typedef struct myStruct {
char charArray[10];
} myStruct;
myStruct myStructure;
myStruct *ptrToStruct = &myStructure;
/* This should change myStructure.charAarray[0] to equal a */
*(ptrToStruct.charArray) = 'a';
I understand that an array is essentially a pointer that is pointing to the first index in the array but the pointer has no data (charArray).
The reason this is so hard for me to understand is because the ptrToStruct is trying to access the pointer's data member charArray but the pointer has no data member charArray and then it's dereferencing it.
Is this sort of like (*ptrToStruct).(*charArray) = 'a'? But the dereferencing operator is being factored out? I apologize for being at all unclear.
UPDATE: The question has been answered. I was misreading code, the code was actually *(myStructure.charArray) and that's how it was altering the first index of the array. I should have also figured this out because as Sid explained pointers do not have the . operator.
ptrToStruct isn't a struct, so
ptrToStruct.charArray
should be
(*ptrToStruct).charArray
or
ptrToStruct->charArray
Then, yes, you can set the character using
*( ptrToStruct->charArray ) = 'a';
or
( ptrToStruct->charArray )[0] = 'a';
This is no different than
char charArray[10];
*charArray = 'a';
and
char charArray[10];
charArray[0] = 'a';
Related
I am getting quite confused alot about pointers in structures.
I have a piece of code which i do no understand fully yet,
the code:
typedef struct{
int fildes // basic file descriptor
char* location // location would be somewhere in /dev/tty*
}context0; // structure named 'context' containing the 2 elements above.
context0 someContext; // create a context struct
process(&readLocation); // takes reference from the function 'readlocation'
// i do not know what this process function does.
uint_16_t readLocation(int8_t *buffer, int16_t n, SomeContext){ // buffer pointer, n size read, and fidles
context0 foo = *(context0*) SomeContext; // ???? What Is Going ON right here ????
return read(foo.fd, buffer, n);
}
I have changed some of the names but its the code which i do not fully understand.
Some questions:
since readLocation function is passed as a reference should it not be defined as void* ? infront of the uint_32_t
main question: what does the context0 foo = * (context0*) SomeContext; do?
ok so it seems that (context0 *) is infact a typecast which is done by (int)bar to set some other type to the type of 'int'. this is done to set the variable bar to the type of context.
this typecast can also be done to a pointer type cast wich would be done as (int*) or (struct name*), or in this case (context0 *).
lastly the pointer outside of the parenthisis dereferences the structure pointer to acces whatever it points towards and places this information in the struct context0 foo.
why this is nessesary i do not know but the syntax points to this.
thanks, oh ur welcome np
and thank u Gábor Angyal, but cannot give points or whatever level 1
Task: I want to swap pointers without reference passing the pointers in the function.
Problem 1: The following code does the job but I think its swapping the "data" instead of swapping the "pointers".
void swappointers(char *ptrX, char *ptrY)
{
char dummy;
dummy = *ptrX;
*ptrX = *ptrY; //LINE
*ptrY = dummy;
}
Problem 2: How the commented line is working? *ptrX means that ptrX is being de-referenced(accessing the value the pointer is directing to). Similar is the case with *ptrY. But why the value being directed by ptrX is being changed here? I mean its actually looking like this:
ValueofX = ValueofY
Thank you :)
Edit:
Solved the first problem.
void swappointers(char **ptrX, char **ptrY)
{
char *dummy = nullptr;
dummy = *ptrX;
*ptrX = *ptrY;
*ptrY = dummy;
}
I think its swapping the "data" instead of swapping the "pointers".
You are correct.
I want to swap pointers without reference passing the pointers in the function.
That's impossible. Unless you pass by reference, changes made inside the function will not be seen by the caller.
template<typename T>
void swap(T &a, T &b){
T backup=a;
a=b;
b=backup;
}
*ptrX = *ptrY; means variable, to which points ptrX, have to have same value as variable to which points ptrY.
About your commented line:
*ptrX = *ptrY; //LINE
In plain English it means:
Put the value of the memory location pointed to by ptrY into the memory location pointed to by ptrX.
I have the following
typedef struct
{
int titleCount;
char** titles;
} myStruct;
And then
...
struct1->titleCount = 2;
struct1->titles = (char**) malloc(sizeof(char *) * (str->titleCount + 1));
...
What would be the correct syntax for using new instead of malloc?
in the example, titles points to an array of pointers to char or most probably actually strings. So I would expect something like:
titles = new char*[str->titleCount]; // or maybe keep the +1
followed by a loop to allocate the individual strings and put pointers to them into the array pointed-to by titles.
If you are porting from C to C++, the better solution would be:
std::vector<std::string> myTitles;
The entire struct is unnecessary.
First of all your code of allocating memory is invalid because you may not write
struct1->titleCount
unless somewhere you wrote
struct struct1 *struct1 = malloc( sizeof( struct struct1 ) );
However from the code you presented it seems that you need to allocate
str->titleCount + 1
elements of type char *
So the corresponding code will look as
str->titleCount = 2;
str->titles = new char * [str->titleCount + 1];
Next time please show a code snippet that could be compiled. From you code it is not clear what is struct1 and str. You only confuse others.
I have the following structure in C++ :
struct wrapper
{
// Param constructor
wrapper(unsigned int _id, const char* _string1, unsigned int _year,
unsigned int _value, unsigned int _usage, const char* _string2)
:
id(_id), year(_year), value(_value), usage(_usage)
{
int len = strlen(_string1);
string1 = new char[len + 1]();
strncpy(string1, _string1, len);
len = strlen(_string2);
string2 = new char[len + 1]();
strncpy(string2, _string2, len);
};
// Destructor
~wrapper()
{
if(string1 != NULL)
delete [] string1;
if(string2 != NULL)
delete [] string2;
}
// Elements
unsigned int id;
unsigned int year;
unsigned int value;
unsigned int usage;
char* string1;
char* string2;
};
In main.cpp let's say I allocate memory for one object of this structure :
wrapper* testObj = new wrapper(125600, "Hello", 2013, 300, 0, "bye bye");
Can I now delete the entire object using pointer arithmetic and a pointer that points to one of the structure elements ?
Something like this :
void* ptr = &(testObj->string2);
ptr -= 0x14;
delete (wrapper*)ptr;
I've tested myself and apparently it works but I'm not 100% sure that is equivalent to delete testObj.
Thanks.
Technically, the code like this would work (ignoring the fact that wrapper testObj should be wrapper* testObj and that the offset is not necessarily 0x14, e.g. debug builds sometimes pad the structures, and maybe some other detail I missed), but it is a horrible, horrible idea. I can't stress hard enough how horrible it is.
Instead of 0x14 you could use offsetof macro.
If you like spending nights in the company of the debugger, sure, feel free to do so.
I will assume that the reason for the question is sheer curiosity about whether it is possible to use pointer arithmetic to navigate from members to parent, and not that you would like to really do it in production code. Please tell me I am right.
Can I now delete the entire object using pointer arithmetic and a pointer that points to one of the structure elements ?
Theoretically, yes.
The pointer that you give to delete needs to have the correct value, and it doesn't really matter whether that value comes from an existing pointer variable, or by "adjusting" one in this manner.
You also need to consider the type of the pointer; if nothing else, you should cast to char* before performing your arithmetic so that you are moving in steps of single bytes. Your current code will not compile because ISO C++ forbids incrementing a pointer of type 'void*' (how big is a void?).
However, I recommend not doing this at all. Your magic number 0x14 is unreliable, given alignment and padding and the potential of your structure to change shape.
Instead, store a pointer to the actual object. Also stop with all the horrid memory mess, and use std::string. At present, your lack of copy constructor is presenting a nasty bug.
You can do this sort of thing with pointer arithmetic. Whether you should is an entirely different story. Consider this macro (I know... I know...) that will give you the base address of a structure given its type, the name of a structure member and a pointer to that member:
#define ADDRESS_FROM_MEMBER(T, member, ptr) reinterpret_cast<T*>( \
reinterpret_cast<unsigned char *>(ptr) - (ptrdiff_t)(&(reinterpret_cast<T*>(0))->member))
Okay, this one has me stumped. I am trying to pass an array of character arrays into my class's constructor. The class has a private attribute which stores a pointer to the array of character arrays. The class may then process the array via the pointer.
Below is some code that demonstrates the desired functionality. But, it won't compile. How do I fix this code so it works?
using namespace std;
const int MAX_LINES = 10, MAX_STRING = 80;
class Alphabetizer{
public:
Alphabetizer(char * inArray[][MAX_STRING]) : input(inArray){};
private:
char * input[MAX_LINES][MAX_STRING];
};
int main(){
char charArray[MAX_LINES][MAX_STRING];
Alphabetizer theAlaphBet(charArray);
return 0;
}
If you're insisting on using C-compatible character pointers, I think you'll have the best luck using a char ** as the type for input. This is more of the usual way to do this (in C at least), and it has the added benefit of not forcing you to define a maximum string size.
As others have pointed out, you can take advantage of std::string instead, which may be a better choice overall.
I'm guessing it's that you're not passing a pointer to char[][], you're passing a char[][].
Also, you should be using std::string instead of char arrays.
std::string will be the most appropriate here! It handles strings and character arrays well enough!
There are few errors in the code. I suppose you are trying to refer to the charArray in the main function from inside the Alphabetizer object. If that is the case the declaration
char * input[MAX_LINES][MAX_STRING];
is wrong because the above declaration makes input an array of MAX_LINE of ( array of MAX_STRING of (char*)). In summary input is an array not a pointer to array of whatever. If you had intended it to be a pointer - which is what rest of your code hints to me - then you have to do the following,
const int MAX_LINES = 10, MAX_STRING = 80;
class Alphabetizer{
public:
Alphabetizer(char ((*ar)[MAX_LINES])[MAX_STRING]) : m_ar(ar){};
private:
char ((*m_ar)[10])[80];
};
int main(){
char charArray[MAX_LINES][MAX_STRING];
char ((*ar)[MAX_LINES])[MAX_STRING] = &charArray;
Alphabetizer theAlaphBet(&charArray);
return 0;
}
Moreover doing,
input(inArray)
is wrong, as it is equivalent to doing the following,
char a[1] = {'a'};
char b[1] = {'p'};
a = b;
assigning an array to another does not copy one over another. You have to do explicit memcpy. (This semantics is not meaningful in c or c++)
It's difficult to tell without seeing the compile errors, but I think the problem might be this line:
Alphabetizer theAlaphBet(charArray);
You are passing the array directly rather than it's address. It should read:
Alphabetizer theAlaphBet( &charArray );
However I think you may be overcomplicating things. You might be better off using a reference rather than a pointer:
const int MAX_LINES = 10, MAX_STRING = 80;
class Alphabetizer{
public:
Alphabetizer(char & inArray[][MAX_STRING]) : input(inArray){};
private:
char & input[MAX_LINES][MAX_STRING];
};
int main(){
char charArray[MAX_LINES][MAX_STRING];
Alphabetizer theAlaphBet(charArray);
return 0;
}
You might also want to look into using std::string instead as this may help to simplify your code.