Sabitha Abraham's profileSaby's spacePhotosBlogLists Tools Help

Blog


    December 14

    Create share, add permission to a user to share folder in c#

    //Creating the share folder and add a user with permission to a share folder

     

    System.Management.ManagementScope scope = new System.Management.ManagementScope(@"\\"MachineName + @"\root\cimv2");

    scope.Connect();

    LogInfo("Creating fileShare..");

    ManagementClass managementClass = new ManagementClass(scope, new ManagementPath("Win32_Share"), null);

    ManagementBaseObject inParams = managementClass.GetMethodParameters("Create");

    inParams["Description"] = shareName;

    inParams["Name"] = shareName;

    inParams["Path"] = sharePath;

    inParams["Type"] = 0x0;

    inParams["Access"] = SecurityDescriptor;  // This is where we add the user with permission. I have shown 2 ways of creating this object below 

    inParams = managementClass.InvokeMethod("Create", inParams, null);

     

     

    //  Getting SecurityDescriptor from the share itself.

    System.Management.ManagementScope scope = new System.Management.ManagementScope(@"\\"MachineName + @"\root\cimv2");

    scope.Connect();

    ManagementObject Win32LogicalSecuritySetting = new ManagementObject(string.Format "{0}:Win32_LogicalShareSecuritySetting.Name='{1}'", scopeString,shareName));

     

    ManagementBaseObject Return = Win32LogicalSecuritySetting.InvokeMethod("GetSecurityDescriptor", null, null);

    Int32 ReturnValue = Convert.ToInt32(Return.Properties["ReturnValue"].Value);

    if (ReturnValue != 0)

        throw new Exception(String.Format("Error when calling GetSecurityDescriptor. Error code : {0}.", ReturnValue));

    SecurityDescriptor = Return.Properties["Descriptor"].Value as ManagementBaseObject;

     

     

    // Creating a new securty description for a new user

    ManagementObject Trustee = new ManagementClass(new ManagementPath("Win32_Trustee"), null);

    Trustee["Domain"] = domainName;

    Trustee["Name"] = userName;

     

    ManagementObject AdminACE = new ManagementClass(new ManagementPath("Win32_Ace"), null);

    AdminACE["AccessMask"] = 2032127;

    AdminACE["AceFlags"] = 3;

    AdminACE["AceType"] = 0;

    AdminACE["Trustee"] = Trustee;

     

    ManagementObject SecurityDescriptor= new ManagementClass(new ManagementPath("Win32_SecurityDescriptor"), null);

    SecurityDescriptor ["ControlFlags"] = 4; //SE_DACL_PRESENT

    SecurityDescriptor ["DACL"] = new object[] { AdminACE };

     

    Delete share or UNC c# or stop sharing share folder

    //Delete a share or UNC in  c#            or             stop sharing a share folder

     

    System.Management.ManagementScope scope = new System.Management.ManagementScope(@"\\machineName\\root\cimv2");

    scope.Connect();

    ObjectQuery oQuery = new ObjectQuery("SELECT * FROM Win32_Share WHERE Name = 'FileShare'");

    ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(scope, oQuery);

    ManagementObjectCollection shares = oSearcher.Get();

    ManagementObjectCollection.ManagementObjectEnumerator sharedEnum = shares.GetEnumerator();

    if (sharedEnum.MoveNext())

    {

    ManagementObject share = (ManagementObject)sharedEnum.Current;

    if (share != null) share.Delete();

    }

    else

    {

    throw new HATestException("FileShare is not found..");

    }  

    September 12

    Disable or Enable network card NIC in powershell

    This is my favorate script.
     
    $adapter=Get-wmiobject win32_NetworkAdapter | where {$_.AdapterType -like 'Ethernet*'} | where { $_.PhysicalAdapter -eq 'True'}  | where { $_.NetEnabled -eq 'True' }; sleep 3; foreach ($adp in $adapter) {$adp.disable()}  sleep 10; foreach ($adp in $adapter) {$adp.Enable()}
     
    This will identify the NIC, disable the NIC, sleep for some time and Enable back. So you can let the box disconnect for a while and connect it back throught this.
     
     

    Redirecting to file from powershell command output

    Redirect to a file
    powershellcommand > outputfile.txt
     
    To append
    powershellcommand >> outputfile.txt
     
     
    Forloop or while loop result we might want to assign it to some variable na dprint it to a file
     
    for(1...100) {$result = Get-DatabaseCopyStatus DatabaseCopy150522 -mailboxServer EXCH-B-204 | fl  *LastLogGenerated*, *LastLogInspected
    *, *LastLogCopyNotified*, *CopyQueueLength*, *LogCopyQueueIncreasing* ; echo $result >> D:\CopyQ.txt; date >> D:\CopyQ.txt; sleep 1; }
    July 22

    Automatic properties in C# 3.0

     

    The new C# compiler that ships in "Orcas" provides an elegant way to make your code more concise while still retaining the flexibility of properties using a new language feature called "automatic properties".  Automatic properties allow you to avoid having to manually declare a private field and write the get/set logic -- instead the compiler can automate creating the private field and the default get/set operations for you.  If we want to write a default getter and setter method for any variable then we could use the below shortcut.

    public string MyProperty { get; set; }

    So, This will be replaced with the following

    private string myProperty;
    public string MyProperty
    {
    get{return myProperty;}
    set{myProperty = value;}
    }

    November 28

    A thought about life

     

     

    Life is like a journey and each of us are drivers, a journey without any obvious destination. Or nobody really knows where they are heading to. That’s why here journey is more important than destination. In this drive we get to see lots of things and meet many people. Some things we see might be interesting to us some might not and what we feel is interesting might not be interesting to others. And what we feel interesting is not interesting to us all the time.

     

    When we go far and far we realize many things. If we are well off in our journey there will be people to pull us down and if we are not doing good there will be people to bother us. There would be days we are sick; there would be moments we feel we are the happiest person on earth. There would be our heydays and tough days. But most of them are momentary.

     

    When you go far and far you meet different kinds of people. There will be people who don’t care who else is there on the road. There will be people who worry about everybody around them. When we look around we see good people, bad people, people with xyz and people without xyz. But it’s all our judgments!!! We see some people are good and we measure some people by their xyz. In reality none exists. Some times on your way you might be treated based on what you are, what you know and what you have but don’t worry about their ignorance. We know that it doesn’t really matter.

     

    It is true what Prince Buddha said “everything in life is constantly changing and impermanent”. “Origin of suffering is the craving for self desire”, which is attachment to desire.  Same thing I heard from a movie in a different way “I call myself a Peaceful Warrior because the battles we fight are on the inside “. When we overcome the silly thoughts from within, we become peaceful warrior with no battles around.

     

    But to some extent we need to have certain aspiration, this helps us to get going with our life and have success in what do we do. But how far we should go? I would say that is the difference between desire and aspiration. And one thing we need to remember here is it’s the journey not the destination because the destination is totally uncertain to us. Then why are we running, rushing, striving hard to reach somewhere as though there is a beautiful palace just a mile away with a fear in mind that it might not be accessible if we are late for 2 minutes.  

     

    Sabitha Abraham

     

    November 08

    Win32 Messages

     

    In windows a message is an integer value; example

           WM_INITDIALOG          =   0110H;

            WM_COMMAND             =   0111H

    Each windows message may have up to two parameters, wParam and lParam. Originally wParam was 16 bit and lParam was 32 bit, but in Win32 they are both 32 bit. Not every message uses these parameters, and each message uses them differently. For example the WM_CLOSE message doesn't use either, and you should ignore them both. The WM_COMMAND message uses both, wParam contains two values, HIWORD(wParam) is the notification message (if applicable) and LOWORD(wParam) is the control or menu id that sent the message. lParam is the HWND (window handle) to the control which sent the message or 0 if the messages isn't from a control.

    HIWORD() and LOWORD() are macros defined by windows (WINUSER.DEF) that single out the two high bytes (High Word) of a 32 bit value (FFFF0000H) and the low word (0000FFFFH) respectively.

     

    WM_SIZE

        WPARAM wParam
        LPARAM lParam;

    wParam
    Specifies the type of resizing requested. This parameter can be one of the following values.
    lParam
    The low-order word of lParam specifies the new width of the client area.
    The high-order word of lParam specifies the new height of the client area.

    Reference Link : http://www.modula2.org/win32tutor/message_loop.php

    Sabitha Abraham

    October 23

    Design patterns

    There are 3 types of design patterns

    Creational

     - which deal with the creation of objects. This patterns abstract the Instantiation process.

    Example

     - Abstract factory

     - Factory Method

     - Singleton

    Structural

    - This patterns are concerned with how classes and objects are composed to form larger structures. This pattern is particularly useful for making independently developed class libraries work together. This patterns ease the design by identifying a simple way to realize relationships between entities   

    Example

     -Adapter

     -Bridge

     -Facade - Used if you want to provide a simple interface to a complex system

     -Decorator

    Behavioral-

     This patterns are concerned with algorithms and assignment of responsibilities between objects. This patterns describes not just patterns of objects or classes but also the patterns of communication  between them. These patterns charectirize complex control flow that's difficult to follow at  run time

    Example

     - Mediator

     - Command

     

    Sabitha Abraham

     
    August 27

    How does number value get stored in memory?

    Suppose you have a declaratio like
     
    char x = -127;
    For any number which is -ve before allocating into the memory, it will be converted to its 2's compliment and then store in the memory.  First bit will have sign(+/-). The allocation in the memory would be
     
    1 0000001.
     
    While retrieving the number, it checks for the sign first if it indicate 1 in the first bit, it will assume it as a negative number and then again take the 2's compliment of the number 0000001. then we get our original number back 1 1111111.
     
    char x = 129;
     
    consider this scenario, here there is an overflow of the variable  x, coz the max value which can be stored in a signed character is 127. If we conside it as unsigned it can hold up to 255. While storing the variable in memory, it doest think of what time of the variable it is(signed/unsigned) it just blindly aloocate the variable in the memory based on the number is  -ve or positive. If its a negative number it converts into 2's compliment and if its a +ve number it just allocate into memory as it is.
    so here the allocation would be
     
    1 0000001.
     
    while retirving the value from memory it first checks for the sign bit, it finds it as 1, then it assumes that it is a -ve number and it takes the 2's compliment of the number so it will be interpreted as
    1 1111111
     
    it is equalent to -127 again.
     
     
     Sabitha Abraham
    May 31

    Creating tree view with spliter

    Create an mfc application with document view architecture unselected.
     
    in CMainFrame::OnCreateClient add the following,

    CRect cr;

    GetClientRect(&cr); CSize paneSize(cr.Width()/100*20, cr.Height());

    CSize paneSize1(cr.Width()/100*80, cr.Height());

    int rc; m_wndSplitter.CreateStatic(this, 1, 2);

    rc = m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CVHDSRootView),paneSize, pContext);

    if (FALSE == rc) return rc;

    return rc;

    add the following in CMainFrame::oncreate()

    CVHDSRootView* pNav = (CVHDSRootView*)m_wndSplitter.GetPane(0,0);

     Sabitha Abraham

    May 30

    check whether 32-bit program is running on 64 OS or not ?

    how to detect programmatically whether your 32-bit program is running on 64-bit Windows?
    BOOL Is64BitWindows()
    {
    #if defined(_WIN64)
     return TRUE;  // 64-bit programs run only on Win64
    #elif defined(_WIN32)
     // 32-bit programs run on both 32-bit and 64-bit Windows
     // so must sniff
     BOOL f64 = FALSE;
     return IsWow64Process(GetCurrentProcess(), &f64) && f64;
    #else
     return FALSE; // Win64 does not support Win16
    #endif
    }
    
    April 23

    Windows Registry?

    The Registry”, is a sort of central Windows database. It’s used both by the operating system and by Windows applications to store persistent information Aside from file associations, the registry is used by Windows applications to store all sorts of information. Some of this information is obvious; user preferences for example. Other kinds of information, like window positions, are more subtle.
    using Microsoft.Win32;
    This will allow us to make use of Windows registry functionality within our C# program.

    How to register a dll?

    Go to the Run item on the Start menum, and type: regsvr32 <path & filename of dll or ocx>

    eg : regsvr32 c:/inetpub/scripts/library.dll

    One use of registry is to use the unmanaged code(dll) from .net platform. for that..

    Register UnmanagedComponent.dll with regsvr32.exe

    March 26

    Win32 faq

    1. What is WINAPI?: Its is #define to __stdcall :- This is a calling convention which is usually used to call Win32 API functions. WINAPI is nothing but another name for __stdcall:

    C Calling convention (__cdecl) : This convention is the default for C/C++ programs (compiler option /Gd). If a project is set to use some other calling convention, we can still declare a function to use __cdecl:
    int __cdecl sumExample (int a, int b);
    1. Arguments are passed from right to left, and placed on the stack.
    2. Stack cleanup is performed by the caller.
    3. Function name is decorated by prefixing it with an underscore character '_' .
    Standard Calling convention(__stdcall) : This convention is usually used to call Win32 API functions. In fact, WINAPI is nothing but another name for __stdcall
    1. Arguments are passed from right to left, and placed on the stack.
    2. Stack cleanup is performed by the called function.
    3. Function name is decorated by prepending an underscore character and appending a '@' character and the number of bytes of stack space required.

    Fast calling convention (__fastcall) : Fast calling convention indicates that the arguments should be placed in registers, rather than on the stack, whenever possible. This reduces the cost of a function call, because operations with registers are faster than with the stack.

    We can explicitly declare a function to use the __fastcall convention as shown:

    int __fastcall sumExample (int a, int b);
    3 windows system dll which holds win32 api?
    kernel32, user32.dll,gdi32.dll.
    March 21

    C++ faq4

    15. What is dynamic cast and static cast?differnt types of casting?

    dynamic_cast can be used only with pointers and references of objects. Its purpose is to ensure that the result of the type conversion is a valid object of the requested class.

    If the base class is not polymorphic(no virtual key word), dynamic_cast would give an error when we try to convert the base class pointer to derived class poiter type. Ie

    derivedClass * derP = dynamic_cast <derivedClass*>( new baseClass) ;//error  baseClass is not polymorphic.

    If the base class is polymorphic then, dynamic_cast performs a special checking during runtime to ensure that the expression gives a valid object of the requested class: and if the check fails at run time it return a null pointer.

    Static_cast : can perform conversion between pointers to related classes, not only from the derived class to its base, but also from base class to its derived. Here no safety check is performed during run time . So it is up to the programmer to ensure the conversion is safe. The advantage here is we can avoid the overhead of type safety check at run time.

    Reinterpret cast: This converts any pointer type to any other pointer type, even of un related class. neither the content pointed nor the pointer type itself is checked

    Const_cast : This is used for manipulating the constness of an object, either to be set or to be removed. This is useful to pass a cost argument to a function that expects a non-const parameter.

      const char * c = "sample text";
      print ( const_cast<char *> (c) );

    typeid : is used for checking the type of an expression:

    typeid (expression)

    C++ faq3

    12. Order of Destructor?

    Class A

    { virtual void fun(){}

     Virtual ~A() ; }

    Class B : public A

    {void fun(){}

    ~B() ; }

    A* a1 = new B();

    Destructor goes to B first and then to A. If the destructor in B is not virtual, the derived class’s destructor will never get invoked.

    In the case of constructor, Constructor can’t be virtual, It goes to B(), then it goes to A() and then to B().

    13.  Why is the initialization list more efficient?

    ClassA (ClassB objB, int x)

    {

                _objB = objB  ;

                _x = x ;

    }

    If you invoke any argument constructor, the following things would happen

    a.       Copy constructor will get called for former parameters if any(ClassB copy cnstr)

    b.      Default constructor will get called for initializing all the parameters in the constructor(ClassA default cnstr to initialize _objB and _x)

    c.       Assignment operator will get called for assigning the values(ClassB assignment opr)

    ClassA(ClassB objB, int x) : _objB(objB), _x(x)

    {}

    a.       Copy constructor will get called for former parameters if any(ClassB copy cnstr)

    b.      Copy constructor will get called for assigning the values(ClassB assignment opr)

    14. Can I create base class object as a member variable in the derived class ?

    Yes.

    March 19

    Win32

    Steps involved in a win32 application.
     
    1. Register the window class. This is done by the following sample code
      const char g_szClassName[] = "sampleWindowClass";
    This variable stores the name of the window class, This will be used to register the window class with the system
    Now for regestering, we create a structure of type WNDCLASSEX  and call the function RegisterClassEx by paasing the structure object as parameter.
     
     WNDCLASSEX wc;
     wc.cbSize        = sizeof(WNDCLASSEX);
        wc.style         = 0;
        wc.lpfnWndProc   = WndProc;
        wc.hInstance     = hInstance;
        wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
        wc.lpszMenuName  = NULL;
        wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
     if(!RegisterClassEx(&wc))
        {
            MessageBox(NULL, "Window Registration Failed!", "Error!",
                MB_ICONEXCLAMATION | MB_OK);
            return 0;
        }
    This code will be written in winMain
     
    2. Creating the window
    Once the class has been registered we can create the window by calling CreateWindowEx api
    HWND hwnd;
     hwnd = CreateWindowEx(
            WS_EX_CLIENTEDGE,
            g_szClassName,
            "The title of my window",
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
            NULL, NULL, hInstance, NULL);
    //Check window creation is failed or not
    if(hwnd == NULL)
        {
            MessageBox(NULL, "Window Creation Failed!", "Error!",
                MB_ICONEXCLAMATION | MB_OK);
            return 0;
        }
    ShowWindow(hwnd, nCmdShow);
       UpdateWindow(hwnd);

    3. Message Loop
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
        {
            TranslateMessage(&Msg);
            DispatchMessage(&Msg);
        }
        return Msg.wParam;
    This is very important part of the program. GetMessage() gets a message from your application's message queue. Any time the user moves the mouse, types on the keyboard, clicks on your window's menu, or does any number of other things, messages are generated by the system and entered into your program's message queue.By calling GetMessage() you are requesting the next available message to be removed from the queue and returned to you for processing.
    4. WinProc
    This is where all the messages that are sent to our window get processed
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch(msg)
        {
            case WM_CLOSE:
                DestroyWindow(hwnd);
            break;
            case WM_DESTROY:
                PostQuitMessage(0);
            break;
            default:
                return DefWindowProc(hwnd, msg, wParam, lParam);
        }
        return 0;
    }
    The window procedure is called for each message, the HWND parameter is the handle of your window
    March 16

    Message Map

    All of the event handling in MFC programs happens behind the scenes" in C++ code that is part of the CWinApp class. Because it is hidden, we need a way to tell the invisible event loop to notify us about events of interest to the application. This is done through a message map. This message map identifies interesting events and then indicates functions to call in response to those events.
     
    void CButtonWindow::HandleButton()
    {
    MessageBeep(-1);
    }

    // The message map
    BEGIN_MESSAGE_MAP(CButtonWindow, CFrameWnd)
    ON_BN_CLICKED(IDB_BUTTON, HandleButton)
    END_MESSAGE_MAP()

    BOOL CButtonApp::InitInstance()
    {
    m_pMainWnd = new CButtonWindow();
    m_pMainWnd->ShowWindow(m_nCmdShow);
    m_pMainWnd->UpdateWindow();
    return TRUE;
    }
     
    The windows application enters the message loop within Winmain to process various windows messages the OS posts to a message queue.
    The message loop, "Loops" until its receives a WM_QUIT message. It uses GetMessage and PeekMessage to retrive messages and 
    PostMessage to sent the retrived messages to Windows procedure.

    Main Classes in MFC

    CObject - This is the base class for most of the MFC classes
    CWinApp- For any application we create, this class will be used.
    CWnd - This collects all common features found in windows, controls, dialogue boxes.
    CFrameWnd-This class is derived from CWnd, this implements a normal framed application window.
    CView-This is used to give user acess to documents though window.
     
    Every application that create in MFC willl have 2 objects
     
    1. An application object that initializes the app and hooks it to windows. This app obj will handle all low level event processing. This class will be derived from CWinApp
    2. A window obj, that acts as the main app window. This class will be derived from CFrameWnd.
     
    bool InitInstance() : his function will be called each time when the instance of the application is invoked. This is the entry poit in our application, this is an overridden function from CWinApp. The actual entry point of all windows application winMain is there in CWinMain.
    March 08

    get set Methods in C# style

    Seting and getting values for member variables in c# is bit differet from C++, But Possibly u can still follow the c++ style if you really want.
    For every private field In C# can have one special public method for writing geter and seter, This is called property.
     
    public class Table
    {
       private string shape;
       public Table(){ }

       public string Shape
      {
          get
         {
            if (shape == "" )
               return "Round";
            else
               return shape;
          }
          set
         {
                shape = value;
          }
      } }
     
    In the above example Shape is the propert for the field shape.
     
    In the application we can make use of these property as shown below,
     
    Table table = new Table();
    table.shape="rect" ;
    string shape=table.shape.

    c++ faqs2

    6. What is virtual function?

    It is a member function of a class, declared with a virtual key word. Normally this would have a different functionality in the derived class and this function call will be resolved at runtime.

    The difference between a non-virtual c++ member function and a virtual member function is, the non-virtual member functions are resolved at compile time. This mechanism is called static binding. Where as the c++ virtual member functions are resolved during run-time. This mechanism is known as dynamic binding. virtual function is used  to have a different functionality in the derived class.

    7. What is polymorphism? Give an example?

    Assume there is a base class named CDR  and a virtual function name Read. There also a derive class named GPRSCDR, with an over ridden function read()

    CDR{ virtual void Initialize() ;}

    GPRSCDR{ void Initialize() ;}

    CDR *cdrPtr;

    cdrPtr = new CDR or cdrPtr = new GPRSCDR

    cdrPtr->Initialize();

    And in my application I will create a base class pointers and at the run time I can pass a either the base class object or the derived class object dynamically. Based on the type of object I create and pass to this base class pointer, the read function of base class or derived class will get called.

    8. What is multiple inheritance and virtual base class?

    Multiple inheritance is used for inheriting one class from two or more classes.

    For example, in the C++ standard library we have a class basic_iostream, which is derived from two base classes basic_ostream and basic_istream. Again these two classes are derived from a base class called basic_ios. 

                                                   Basic_ios

                                  Basic_istream          Basic_ostream   

                                             Basic_iostream 

    But here a potential problem exists for basic_iostream. Class basic_iostream could contain two copies of the members of class basic_ios(one inherited via class basic_istream and one inherited via class basic_ostream). This problem is called dreeded diamond problem. Such a situation would be ambiguous and would result in a compilation error, because the compiler would not know which version of the members from class basic_ios to use. Using virtual base classes solves the problem.

    Class base

    {          Public: virtual void print() const = 0;  }

    Class DerivedOne: virtual public base

    {    public : void print() const { cout << “derived1” }   }

    Class DerivedTwo: virtual public base

    {   public : void print () const {cout<< “Derived2” }    }

    Class Multiple:public DerivedOne, public DerivedTwo

    {  public: void print() const{derivedTwo::print()} }

    9. How to avoid the ambiguity by using a qualified class name ?

    class D : public B2, public B3---This is valid

    In this case whenever we access a function from indirect base class A. Use thequalified name like.. B2::A->fun()

    10. What's the difference between char * and char []?

      

    char *p = "abcde"; // LINE A

    char q[] = "ABCDE";

     

    Well, they are not the same. p is a pointer, a variable in its own

    right with its own memory, that is being initialized to point to the address

    of "abcd", an unnamed string literal.

     

    p will be pointing at the location of where the a is.

     

    With q, it is actually the name for an array, specifically a 6

    Character array. It is as if it were declared as:

     

    char q[] = { 'A', 'B', 'C', 'D', 'E', '\0' };

    Here q does not point at the array of chars, it actually is the

    beginning location of the array of chars, 6 of them.

     

    With those things in mind, to be clear, note that

     

    p is of type char * and q is of type char [6]. In fact, the pointer can

    point at the array:

     

    p = q; // ok, p points at the location holding the A, aka &q[0]

    we can even write that:

    p = &q[0];

    The opposite is not true:

    q = p; // error, can't assign to an array like this

    strcpy(q, p); // copy char at a time (needs to be large enough to hold)

    although given the original definition from LINE A the opposite strcpy

    would not hold:

    strcpy(p, q); /* undefined behavior */

     

    as you should assume that a string literal of the form used to

    initialize p is not a writable entity nor may it be unique.

     

    Note that the sizeof both of these are different while strlen() is the

    same:

     

    G:\tmp>type ptrarr.c

    #include <stdio.h>

    #include <string.h>

     

    char *p = "abcde";

    char q[] = "ABCDE";

     

    int main()

    {

        printf("so p=%d\n", sizeof(p));

        printf("so q=%d\n", sizeof(q));

        printf("sl p=%d\n", strlen(p));

        printf("sl q=%d\n", strlen(q));

     

        return 0;

    }

    so p=4

    so q=6

    sl p=5

    sl q=5

     

    Note that the size of a pointer to a char may not be 4 on all machines,

    but that the size of q will always be 6 characters.

     --Saby-